From 42c044fa2e4f878d7e2f92cdb3fa638c1b2cd86f Mon Sep 17 00:00:00 2001 From: "github-merge-queue[bot]" Date: Tue, 1 Oct 2024 00:01:00 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20actix/ac?= =?UTF-8?q?tix-net@af00dada5c2fbbc9be4a8be0c14572d2835476e6=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .lock | 0 .nojekyll | 0 actix_codec/all.html | 1 + actix_codec/bcodec/struct.BytesCodec.html | 11 + actix_codec/fn.poll_read_buf.html | 35 + actix_codec/framed/struct.Framed.html | 11 + actix_codec/framed/struct.FramedParts.html | 11 + actix_codec/index.html | 6 + actix_codec/lines/struct.LinesCodec.html | 11 + actix_codec/sidebar-items.js | 1 + actix_codec/struct.BytesCodec.html | 29 + actix_codec/struct.Framed.html | 117 ++ actix_codec/struct.FramedParts.html | 43 + actix_codec/struct.LinesCodec.html | 31 + actix_codec/struct.ReadBuf.html | 83 + actix_codec/trait.AsyncRead.html | 106 ++ actix_codec/trait.AsyncWrite.html | 334 ++++ actix_codec/trait.Decoder.html | 130 ++ actix_codec/trait.Encoder.html | 21 + actix_macros/all.html | 1 + actix_macros/attr.main.html | 7 + actix_macros/attr.test.html | 7 + actix_macros/index.html | 7 + actix_macros/sidebar-items.js | 1 + actix_rt/all.html | 1 + actix_rt/arbiter/struct.Arbiter.html | 11 + actix_rt/arbiter/struct.ArbiterHandle.html | 11 + actix_rt/attr.main.html | 7 + actix_rt/attr.test.html | 7 + actix_rt/fn.spawn.html | 24 + actix_rt/index.html | 35 + actix_rt/macro.pin!.html | 11 + actix_rt/macro.pin.html | 104 ++ actix_rt/net/index.html | 3 + actix_rt/net/sidebar-items.js | 1 + actix_rt/net/struct.Ready.html | 80 + actix_rt/net/struct.TcpListener.html | 198 +++ actix_rt/net/struct.TcpSocket.html | 394 +++++ actix_rt/net/struct.TcpStream.html | 718 ++++++++ actix_rt/net/struct.UdpSocket.html | 1030 ++++++++++++ actix_rt/net/struct.UnixDatagram.html | 868 ++++++++++ actix_rt/net/struct.UnixListener.html | 90 + actix_rt/net/struct.UnixStream.html | 575 +++++++ actix_rt/runtime/struct.Runtime.html | 11 + actix_rt/sidebar-items.js | 1 + actix_rt/signal/fn.ctrl_c.html | 39 + actix_rt/signal/index.html | 2 + actix_rt/signal/sidebar-items.js | 1 + actix_rt/signal/unix/fn.signal.html | 25 + actix_rt/signal/unix/index.html | 3 + actix_rt/signal/unix/sidebar-items.js | 1 + actix_rt/signal/unix/struct.Signal.html | 119 ++ actix_rt/signal/unix/struct.SignalKind.html | 63 + actix_rt/struct.Arbiter.html | 37 + actix_rt/struct.ArbiterHandle.html | 26 + actix_rt/struct.Runtime.html | 85 + actix_rt/struct.System.html | 29 + actix_rt/struct.SystemRunner.html | 15 + actix_rt/system/struct.System.html | 11 + actix_rt/system/struct.SystemRunner.html | 11 + actix_rt/task/fn.spawn_blocking.html | 86 + actix_rt/task/fn.yield_now.html | 24 + actix_rt/task/index.html | 2 + actix_rt/task/sidebar-items.js | 1 + actix_rt/task/struct.JoinError.html | 63 + actix_rt/task/struct.JoinHandle.html | 291 ++++ actix_rt/time/fn.interval.html | 48 + actix_rt/time/fn.interval_at.html | 23 + actix_rt/time/fn.sleep.html | 36 + actix_rt/time/fn.sleep_until.html | 31 + actix_rt/time/fn.timeout.html | 47 + actix_rt/time/index.html | 9 + actix_rt/time/sidebar-items.js | 1 + actix_rt/time/struct.Instant.html | 96 ++ actix_rt/time/struct.Interval.html | 144 ++ actix_rt/time/struct.Sleep.html | 152 ++ actix_rt/time/struct.Timeout.html | 114 ++ actix_server/all.html | 1 + actix_server/builder/enum.MpTcp.html | 11 + .../builder/struct.ServerBuilder.html | 11 + actix_server/enum.MpTcp.html | 29 + actix_server/handle/struct.ServerHandle.html | 11 + actix_server/index.html | 2 + actix_server/server/struct.Server.html | 11 + actix_server/sidebar-items.js | 1 + actix_server/struct.Server.html | 169 ++ actix_server/struct.ServerBuilder.html | 107 ++ actix_server/struct.ServerHandle.html | 23 + actix_server/struct.TestServer.html | 40 + .../test_server/struct.TestServer.html | 11 + actix_service/all.html | 1 + actix_service/apply/fn.apply_fn.html | 11 + actix_service/apply/fn.apply_fn_factory.html | 11 + actix_service/apply_cfg/fn.apply_cfg.html | 11 + .../apply_cfg/fn.apply_cfg_factory.html | 11 + actix_service/boxed/fn.factory.html | 11 + actix_service/boxed/fn.rc_service.html | 5 + actix_service/boxed/fn.service.html | 5 + actix_service/boxed/index.html | 2 + actix_service/boxed/sidebar-items.js | 1 + .../boxed/struct.BoxServiceFactory.html | 29 + actix_service/boxed/type.BoxFuture.html | 2 + actix_service/boxed/type.BoxService.html | 2 + actix_service/boxed/type.RcService.html | 2 + actix_service/ext/trait.ServiceExt.html | 11 + .../ext/trait.ServiceFactoryExt.html | 11 + actix_service/ext/trait.TransformExt.html | 11 + actix_service/fn.apply.html | 5 + actix_service/fn.apply_cfg.html | 9 + actix_service/fn.apply_cfg_factory.html | 11 + actix_service/fn.apply_fn.html | 10 + actix_service/fn.apply_fn_factory.html | 10 + actix_service/fn.fn_factory.html | 38 + actix_service/fn.fn_factory_with_config.html | 31 + actix_service/fn.fn_service.html | 6 + actix_service/fn.into_service.html | 4 + actix_service/fn.map_config.html | 10 + actix_service/fn.unit_config.html | 4 + actix_service/fn_service/fn.fn_factory.html | 11 + .../fn_service/fn.fn_factory_with_config.html | 11 + actix_service/fn_service/fn.fn_service.html | 11 + actix_service/index.html | 3 + actix_service/macro.always_ready!.html | 11 + actix_service/macro.always_ready.html | 24 + actix_service/macro.forward_ready!.html | 11 + actix_service/macro.forward_ready.html | 28 + actix_service/map_config/fn.map_config.html | 11 + actix_service/map_config/fn.unit_config.html | 11 + actix_service/sidebar-items.js | 1 + actix_service/struct.ApplyTransform.html | 36 + actix_service/trait.IntoService.html | 8 + actix_service/trait.IntoServiceFactory.html | 8 + actix_service/trait.Service.html | 71 + actix_service/trait.ServiceExt.html | 40 + actix_service/trait.ServiceFactory.html | 34 + actix_service/trait.ServiceFactoryExt.html | 37 + actix_service/trait.Transform.html | 68 + actix_service/trait.TransformExt.html | 11 + actix_service/transform/fn.apply.html | 11 + .../transform/struct.ApplyTransform.html | 11 + actix_service/transform/trait.Transform.html | 11 + actix_tls/accept/enum.TlsError.html | 45 + .../accept/fn.max_concurrent_tls_connect.html | 5 + actix_tls/accept/index.html | 2 + actix_tls/accept/native_tls/index.html | 3 + .../accept/native_tls/reexports/index.html | 3 + .../native_tls/reexports/sidebar-items.js | 1 + .../native_tls/reexports/struct.Error.html | 18 + .../reexports/struct.TlsAcceptor.html | 29 + actix_tls/accept/native_tls/sidebar-items.js | 1 + .../accept/native_tls/struct.Acceptor.html | 38 + .../native_tls/struct.AcceptorService.html | 27 + .../accept/native_tls/struct.TlsStream.html | 39 + actix_tls/accept/openssl/index.html | 3 + .../reexports/enum.HandshakeError.html | 32 + actix_tls/accept/openssl/reexports/index.html | 2 + .../accept/openssl/reexports/sidebar-items.js | 1 + .../openssl/reexports/struct.AlpnError.html | 24 + .../openssl/reexports/struct.Error.html | 18 + .../accept/openssl/reexports/struct.Ssl.html | 330 ++++ .../openssl/reexports/struct.SslAcceptor.html | 48 + .../reexports/struct.SslAcceptorBuilder.html | 326 ++++ actix_tls/accept/openssl/sidebar-items.js | 1 + actix_tls/accept/openssl/struct.Acceptor.html | 38 + .../openssl/struct.AcceptorService.html | 27 + .../accept/openssl/struct.TlsStream.html | 83 + actix_tls/accept/rustls_0_20/index.html | 3 + .../accept/rustls_0_20/reexports/index.html | 2 + .../rustls_0_20/reexports/sidebar-items.js | 1 + .../reexports/struct.ServerConfig.html | 82 + actix_tls/accept/rustls_0_20/sidebar-items.js | 1 + .../accept/rustls_0_20/struct.Acceptor.html | 38 + .../rustls_0_20/struct.AcceptorService.html | 27 + .../accept/rustls_0_20/struct.TlsStream.html | 36 + actix_tls/accept/rustls_0_21/index.html | 3 + .../accept/rustls_0_21/reexports/index.html | 2 + .../rustls_0_21/reexports/sidebar-items.js | 1 + .../reexports/struct.ServerConfig.html | 92 ++ actix_tls/accept/rustls_0_21/sidebar-items.js | 1 + .../accept/rustls_0_21/struct.Acceptor.html | 38 + .../rustls_0_21/struct.AcceptorService.html | 27 + .../accept/rustls_0_21/struct.TlsStream.html | 36 + actix_tls/accept/rustls_0_22/index.html | 3 + .../accept/rustls_0_22/reexports/index.html | 2 + .../rustls_0_22/reexports/sidebar-items.js | 1 + .../reexports/struct.ServerConfig.html | 116 ++ actix_tls/accept/rustls_0_22/sidebar-items.js | 1 + .../accept/rustls_0_22/struct.Acceptor.html | 38 + .../rustls_0_22/struct.AcceptorService.html | 27 + .../accept/rustls_0_22/struct.TlsStream.html | 36 + actix_tls/accept/rustls_0_23/index.html | 3 + .../accept/rustls_0_23/reexports/index.html | 2 + .../rustls_0_23/reexports/sidebar-items.js | 1 + .../reexports/struct.ServerConfig.html | 169 ++ actix_tls/accept/rustls_0_23/sidebar-items.js | 1 + .../accept/rustls_0_23/struct.Acceptor.html | 38 + .../rustls_0_23/struct.AcceptorService.html | 27 + .../accept/rustls_0_23/struct.TlsStream.html | 36 + actix_tls/accept/sidebar-items.js | 1 + actix_tls/all.html | 1 + .../connect/connection/struct.Connection.html | 11 + .../connect/connector/struct.Connector.html | 11 + .../connector/struct.ConnectorService.html | 11 + actix_tls/connect/enum.ConnectError.html | 29 + .../connect/error/enum.ConnectError.html | 11 + actix_tls/connect/host/trait.Host.html | 11 + actix_tls/connect/index.html | 13 + .../connect/info/struct.ConnectInfo.html | 11 + actix_tls/connect/native_tls/index.html | 3 + .../connect/native_tls/reexports/index.html | 3 + .../native_tls/reexports/sidebar-items.js | 1 + .../reexports/struct.AsyncTlsStream.html | 54 + .../reexports/struct.TlsConnector.html | 49 + actix_tls/connect/native_tls/sidebar-items.js | 1 + .../native_tls/struct.TlsConnector.html | 49 + actix_tls/connect/openssl/index.html | 3 + .../reexports/enum.HandshakeError.html | 32 + .../connect/openssl/reexports/index.html | 2 + .../openssl/reexports/sidebar-items.js | 1 + .../reexports/struct.AsyncSslStream.html | 94 ++ .../openssl/reexports/struct.Error.html | 18 + .../reexports/struct.SslConnector.html | 35 + .../reexports/struct.SslConnectorBuilder.html | 326 ++++ .../openssl/reexports/struct.SslMethod.html | 31 + actix_tls/connect/openssl/sidebar-items.js | 1 + .../connect/openssl/struct.TlsConnector.html | 36 + .../openssl/struct.TlsConnectorService.html | 31 + actix_tls/connect/resolve/trait.Resolve.html | 11 + .../connect/resolver/struct.Resolver.html | 11 + .../resolver/struct.ResolverService.html | 11 + .../fn.native_roots_cert_store.html | 3 + .../fn.webpki_roots_cert_store.html | 2 + actix_tls/connect/rustls_0_20/index.html | 3 + .../connect/rustls_0_20/reexports/index.html | 4 + .../rustls_0_20/reexports/sidebar-items.js | 1 + .../reexports/static.TLS_SERVER_ROOTS.html | 1 + .../reexports/struct.AsyncTlsStream.html | 49 + .../reexports/struct.ClientConfig.html | 63 + .../connect/rustls_0_20/sidebar-items.js | 1 + .../rustls_0_20/struct.TlsConnector.html | 36 + .../struct.TlsConnectorService.html | 31 + .../fn.native_roots_cert_store.html | 3 + .../fn.webpki_roots_cert_store.html | 2 + actix_tls/connect/rustls_0_21/index.html | 3 + .../reexports/constant.TLS_SERVER_ROOTS.html | 1 + .../connect/rustls_0_21/reexports/index.html | 3 + .../rustls_0_21/reexports/sidebar-items.js | 1 + .../reexports/struct.AsyncTlsStream.html | 49 + .../reexports/struct.ClientConfig.html | 60 + .../connect/rustls_0_21/sidebar-items.js | 1 + .../rustls_0_21/struct.TlsConnector.html | 36 + .../struct.TlsConnectorService.html | 31 + .../fn.native_roots_cert_store.html | 3 + .../fn.webpki_roots_cert_store.html | 2 + actix_tls/connect/rustls_0_22/index.html | 3 + .../reexports/constant.TLS_SERVER_ROOTS.html | 1 + .../connect/rustls_0_22/reexports/index.html | 3 + .../rustls_0_22/reexports/sidebar-items.js | 1 + .../reexports/struct.AsyncTlsStream.html | 49 + .../reexports/struct.ClientConfig.html | 84 + .../connect/rustls_0_22/sidebar-items.js | 1 + .../rustls_0_22/struct.TlsConnector.html | 36 + .../struct.TlsConnectorService.html | 31 + .../fn.native_roots_cert_store.html | 3 + .../fn.webpki_roots_cert_store.html | 2 + actix_tls/connect/rustls_0_23/index.html | 3 + .../reexports/constant.TLS_SERVER_ROOTS.html | 1 + .../connect/rustls_0_23/reexports/index.html | 3 + .../rustls_0_23/reexports/sidebar-items.js | 1 + .../reexports/struct.AsyncTlsStream.html | 51 + .../reexports/struct.ClientConfig.html | 137 ++ .../connect/rustls_0_23/sidebar-items.js | 1 + .../rustls_0_23/struct.TlsConnector.html | 36 + .../struct.TlsConnectorService.html | 31 + actix_tls/connect/sidebar-items.js | 1 + actix_tls/connect/struct.ConnectInfo.html | 69 + actix_tls/connect/struct.Connection.html | 61 + actix_tls/connect/struct.Connector.html | 36 + .../connect/struct.ConnectorService.html | 31 + actix_tls/connect/struct.Resolver.html | 34 + actix_tls/connect/struct.ResolverService.html | 30 + actix_tls/connect/tcp/index.html | 3 + actix_tls/connect/tcp/sidebar-items.js | 1 + .../connect/tcp/struct.TcpConnector.html | 33 + .../tcp/struct.TcpConnectorService.html | 29 + actix_tls/connect/trait.Host.html | 17 + actix_tls/connect/trait.Resolve.html | 58 + actix_tls/index.html | 2 + actix_tls/sidebar-items.js | 1 + actix_tracing/all.html | 1 + actix_tracing/fn.trace.html | 17 + actix_tracing/index.html | 4 + actix_tracing/sidebar-items.js | 1 + actix_tracing/struct.TracingService.html | 49 + actix_tracing/struct.TracingTransform.html | 31 + actix_utils/all.html | 1 + actix_utils/counter/index.html | 2 + actix_utils/counter/sidebar-items.js | 1 + actix_utils/counter/struct.Counter.html | 19 + actix_utils/counter/struct.CounterGuard.html | 12 + actix_utils/future/either/enum.Either.html | 11 + actix_utils/future/enum.Either.html | 50 + actix_utils/future/fn.err.html | 7 + actix_utils/future/fn.ok.html | 7 + actix_utils/future/fn.poll_fn.html | 20 + actix_utils/future/fn.ready.html | 11 + actix_utils/future/index.html | 2 + actix_utils/future/poll_fn/fn.poll_fn.html | 11 + actix_utils/future/poll_fn/struct.PollFn.html | 11 + actix_utils/future/ready/fn.err.html | 11 + actix_utils/future/ready/fn.ok.html | 11 + actix_utils/future/ready/fn.ready.html | 11 + actix_utils/future/ready/struct.Ready.html | 11 + actix_utils/future/sidebar-items.js | 1 + actix_utils/future/struct.PollFn.html | 21 + actix_utils/future/struct.Ready.html | 33 + actix_utils/index.html | 2 + actix_utils/sidebar-items.js | 1 + bytestring/all.html | 1 + bytestring/index.html | 3 + bytestring/sidebar-items.js | 1 + bytestring/struct.ByteString.html | 1302 +++++++++++++++ crates.js | 2 + help.html | 1 + index.html | 1 + local_channel/all.html | 1 + local_channel/index.html | 3 + local_channel/mpsc/fn.channel.html | 3 + local_channel/mpsc/index.html | 2 + local_channel/mpsc/sidebar-items.js | 1 + local_channel/mpsc/struct.Receiver.html | 27 + local_channel/mpsc/struct.SendError.html | 21 + local_channel/mpsc/struct.Sender.html | 30 + local_channel/sidebar-items.js | 1 + local_waker/all.html | 1 + local_waker/index.html | 3 + local_waker/sidebar-items.js | 1 + local_waker/struct.LocalWaker.html | 29 + search-index.js | 4 + .../actix_codec/actix_codec-desc-0-.js | 1 + .../actix_macros/actix_macros-desc-0-.js | 1 + search.desc/actix_rt/actix_rt-desc-0-.js | 1 + .../actix_server/actix_server-desc-0-.js | 1 + .../actix_service/actix_service-desc-0-.js | 1 + search.desc/actix_tls/actix_tls-desc-0-.js | 1 + .../actix_tracing/actix_tracing-desc-0-.js | 1 + .../actix_utils/actix_utils-desc-0-.js | 1 + search.desc/bytestring/bytestring-desc-0-.js | 1 + .../local_channel/local_channel-desc-0-.js | 1 + .../local_waker/local_waker-desc-0-.js | 1 + settings.html | 1 + src-files.js | 3 + src/actix_codec/bcodec.rs.html | 65 + src/actix_codec/framed.rs.html | 825 ++++++++++ src/actix_codec/lib.rs.html | 57 + src/actix_codec/lines.rs.html | 317 ++++ src/actix_macros/lib.rs.html | 443 +++++ src/actix_rt/arbiter.rs.html | 635 +++++++ src/actix_rt/lib.rs.html | 419 +++++ src/actix_rt/runtime.rs.html | 299 ++++ src/actix_rt/system.rs.html | 715 ++++++++ src/actix_server/accept.rs.html | 925 +++++++++++ src/actix_server/availability.rs.html | 243 +++ src/actix_server/builder.rs.html | 757 +++++++++ src/actix_server/handle.rs.html | 113 ++ src/actix_server/join_all.rs.html | 157 ++ src/actix_server/lib.rs.html | 73 + src/actix_server/server.rs.html | 737 +++++++++ src/actix_server/service.rs.html | 325 ++++ src/actix_server/signals.rs.html | 217 +++ src/actix_server/socket.rs.html | 587 +++++++ src/actix_server/test_server.rs.html | 307 ++++ src/actix_server/waker_queue.rs.html | 169 ++ src/actix_server/worker.rs.html | 1463 +++++++++++++++++ src/actix_service/and_then.rs.html | 651 ++++++++ src/actix_service/apply.rs.html | 547 ++++++ src/actix_service/apply_cfg.rs.html | 465 ++++++ src/actix_service/boxed.rs.html | 277 ++++ src/actix_service/ext.rs.html | 249 +++ src/actix_service/fn_service.rs.html | 849 ++++++++++ src/actix_service/lib.rs.html | 651 ++++++++ src/actix_service/macros.rs.html | 375 +++++ src/actix_service/map.rs.html | 489 ++++++ src/actix_service/map_config.rs.html | 257 +++ src/actix_service/map_err.rs.html | 499 ++++++ src/actix_service/map_init_err.rs.html | 199 +++ src/actix_service/pipeline.rs.html | 617 +++++++ src/actix_service/ready.rs.html | 109 ++ src/actix_service/then.rs.html | 669 ++++++++ src/actix_service/transform.rs.html | 543 ++++++ src/actix_service/transform_err.rs.html | 191 +++ src/actix_tls/accept/mod.rs.html | 263 +++ src/actix_tls/accept/native_tls.rs.html | 365 ++++ src/actix_tls/accept/openssl.rs.html | 417 +++++ src/actix_tls/accept/rustls_0_20.rs.html | 397 +++++ src/actix_tls/accept/rustls_0_21.rs.html | 397 +++++ src/actix_tls/accept/rustls_0_22.rs.html | 397 +++++ src/actix_tls/accept/rustls_0_23.rs.html | 397 +++++ src/actix_tls/connect/connect_addrs.rs.html | 165 ++ src/actix_tls/connect/connection.rs.html | 103 ++ src/actix_tls/connect/connector.rs.html | 257 +++ src/actix_tls/connect/error.rs.html | 89 + src/actix_tls/connect/host.rs.html | 143 ++ src/actix_tls/connect/info.rs.html | 503 ++++++ src/actix_tls/connect/mod.rs.html | 133 ++ src/actix_tls/connect/native_tls.rs.html | 181 ++ src/actix_tls/connect/openssl.rs.html | 303 ++++ src/actix_tls/connect/resolve.rs.html | 125 ++ src/actix_tls/connect/resolver.rs.html | 403 +++++ src/actix_tls/connect/rustls_0_20.rs.html | 359 ++++ src/actix_tls/connect/rustls_0_21.rs.html | 355 ++++ src/actix_tls/connect/rustls_0_22.rs.html | 327 ++++ src/actix_tls/connect/rustls_0_23.rs.html | 327 ++++ src/actix_tls/connect/tcp.rs.html | 409 +++++ src/actix_tls/connect/uri.rs.html | 127 ++ src/actix_tls/lib.rs.html | 35 + src/actix_tracing/lib.rs.html | 511 ++++++ src/actix_utils/counter.rs.html | 199 +++ src/actix_utils/future/either.rs.html | 191 +++ src/actix_utils/future/mod.rs.html | 23 + src/actix_utils/future/poll_fn.rs.html | 249 +++ src/actix_utils/future/ready.rs.html | 265 +++ src/actix_utils/lib.rs.html | 19 + src/bytestring/lib.rs.html | 937 +++++++++++ src/local_channel/lib.rs.html | 21 + src/local_channel/mpsc.rs.html | 511 ++++++ src/local_waker/lib.rs.html | 147 ++ static.files/COPYRIGHT-23e9bde6c69aea69.txt | 50 + .../FiraSans-LICENSE-db4b642586e02d97.txt | 98 ++ .../FiraSans-Medium-8f9a781e4970d388.woff2 | Bin 0 -> 132780 bytes .../FiraSans-Regular-018c141bf0843ffd.woff2 | Bin 0 -> 129188 bytes .../LICENSE-APACHE-b91fa81cba47b86a.txt | 201 +++ static.files/LICENSE-MIT-65090b722b3f6c56.txt | 23 + ...anumBarunGothic-0f09457c7a19b7c6.ttf.woff2 | Bin 0 -> 399468 bytes ...umBarunGothic-LICENSE-18c5adf4b52b4041.txt | 103 ++ ...ourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 | Bin 0 -> 44896 bytes ...SourceCodePro-LICENSE-d180d465a756484a.txt | 97 ++ ...CodePro-Regular-562dcc5011b6de7d.ttf.woff2 | Bin 0 -> 52228 bytes ...odePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 | Bin 0 -> 52348 bytes ...urceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 | Bin 0 -> 81540 bytes ...SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 | Bin 0 -> 59716 bytes .../SourceSerif4-LICENSE-3bb119e13b1258b7.md | 98 ++ ...eSerif4-Regular-46f98efaafac5295.ttf.woff2 | Bin 0 -> 76260 bytes static.files/favicon-2c020d218678b618.svg | 24 + .../favicon-32x32-422f7d1d52889060.png | Bin 0 -> 1125 bytes static.files/main-54bc299d2a5e4e43.js | 11 + static.files/normalize-76eba96aa4d2e634.css | 2 + static.files/noscript-0111fcff984fae8f.css | 1 + static.files/rust-logo-151179464ae7ed46.svg | 61 + static.files/rustdoc-b778ab399e080a4b.css | 53 + .../scrape-examples-46fc985aa763a438.js | 1 + static.files/search-e056c65ede92db13.js | 6 + static.files/settings-805db61a62df4bd2.js | 17 + static.files/src-script-e66d777a5a92e9b2.js | 1 + static.files/storage-1d39b6787ed640ff.js | 23 + .../actix_service/ext/trait.ServiceExt.js | 9 + .../ext/trait.ServiceFactoryExt.js | 9 + .../actix_service/ext/trait.TransformExt.js | 9 + trait.impl/actix_service/trait.IntoService.js | 9 + .../actix_service/trait.IntoServiceFactory.js | 9 + trait.impl/actix_service/trait.Service.js | 9 + .../actix_service/trait.ServiceFactory.js | 9 + .../transform/trait.Transform.js | 9 + .../actix_tls/connect/host/trait.Host.js | 9 + trait.impl/core/borrow/trait.Borrow.js | 9 + trait.impl/core/clone/trait.Clone.js | 9 + trait.impl/core/cmp/trait.Eq.js | 9 + trait.impl/core/cmp/trait.Ord.js | 9 + trait.impl/core/cmp/trait.PartialEq.js | 9 + trait.impl/core/cmp/trait.PartialOrd.js | 9 + trait.impl/core/convert/trait.AsRef.js | 9 + trait.impl/core/convert/trait.From.js | 9 + trait.impl/core/convert/trait.TryFrom.js | 9 + trait.impl/core/default/trait.Default.js | 9 + trait.impl/core/error/trait.Error.js | 9 + trait.impl/core/fmt/trait.Debug.js | 9 + trait.impl/core/fmt/trait.Display.js | 9 + trait.impl/core/future/future/trait.Future.js | 9 + trait.impl/core/hash/trait.Hash.js | 9 + trait.impl/core/marker/trait.Copy.js | 9 + trait.impl/core/marker/trait.Freeze.js | 9 + trait.impl/core/marker/trait.Send.js | 9 + .../core/marker/trait.StructuralPartialEq.js | 9 + trait.impl/core/marker/trait.Sync.js | 9 + trait.impl/core/marker/trait.Unpin.js | 9 + trait.impl/core/ops/deref/trait.Deref.js | 9 + trait.impl/core/ops/deref/trait.DerefMut.js | 9 + trait.impl/core/ops/drop/trait.Drop.js | 9 + .../panic/unwind_safe/trait.RefUnwindSafe.js | 9 + .../panic/unwind_safe/trait.UnwindSafe.js | 9 + .../futures_core/stream/trait.Stream.js | 9 + trait.impl/futures_sink/trait.Sink.js | 9 + trait.impl/serde/de/trait.Deserialize.js | 9 + trait.impl/serde/ser/trait.Serialize.js | 9 + .../tokio/io/async_read/trait.AsyncRead.js | 9 + .../tokio/io/async_write/trait.AsyncWrite.js | 9 + .../tokio_util/codec/decoder/trait.Decoder.js | 9 + .../tokio_util/codec/encoder/trait.Encoder.js | 9 + type.impl/alloc/boxed/struct.Box.js | 9 + type.impl/alloc/rc/struct.Rc.js | 9 + type.impl/core/pin/struct.Pin.js | 9 + 501 files changed, 42863 insertions(+) create mode 100644 .lock create mode 100644 .nojekyll create mode 100644 actix_codec/all.html create mode 100644 actix_codec/bcodec/struct.BytesCodec.html create mode 100644 actix_codec/fn.poll_read_buf.html create mode 100644 actix_codec/framed/struct.Framed.html create mode 100644 actix_codec/framed/struct.FramedParts.html create mode 100644 actix_codec/index.html create mode 100644 actix_codec/lines/struct.LinesCodec.html create mode 100644 actix_codec/sidebar-items.js create mode 100644 actix_codec/struct.BytesCodec.html create mode 100644 actix_codec/struct.Framed.html create mode 100644 actix_codec/struct.FramedParts.html create mode 100644 actix_codec/struct.LinesCodec.html create mode 100644 actix_codec/struct.ReadBuf.html create mode 100644 actix_codec/trait.AsyncRead.html create mode 100644 actix_codec/trait.AsyncWrite.html create mode 100644 actix_codec/trait.Decoder.html create mode 100644 actix_codec/trait.Encoder.html create mode 100644 actix_macros/all.html create mode 100644 actix_macros/attr.main.html create mode 100644 actix_macros/attr.test.html create mode 100644 actix_macros/index.html create mode 100644 actix_macros/sidebar-items.js create mode 100644 actix_rt/all.html create mode 100644 actix_rt/arbiter/struct.Arbiter.html create mode 100644 actix_rt/arbiter/struct.ArbiterHandle.html create mode 100644 actix_rt/attr.main.html create mode 100644 actix_rt/attr.test.html create mode 100644 actix_rt/fn.spawn.html create mode 100644 actix_rt/index.html create mode 100644 actix_rt/macro.pin!.html create mode 100644 actix_rt/macro.pin.html create mode 100644 actix_rt/net/index.html create mode 100644 actix_rt/net/sidebar-items.js create mode 100644 actix_rt/net/struct.Ready.html create mode 100644 actix_rt/net/struct.TcpListener.html create mode 100644 actix_rt/net/struct.TcpSocket.html create mode 100644 actix_rt/net/struct.TcpStream.html create mode 100644 actix_rt/net/struct.UdpSocket.html create mode 100644 actix_rt/net/struct.UnixDatagram.html create mode 100644 actix_rt/net/struct.UnixListener.html create mode 100644 actix_rt/net/struct.UnixStream.html create mode 100644 actix_rt/runtime/struct.Runtime.html create mode 100644 actix_rt/sidebar-items.js create mode 100644 actix_rt/signal/fn.ctrl_c.html create mode 100644 actix_rt/signal/index.html create mode 100644 actix_rt/signal/sidebar-items.js create mode 100644 actix_rt/signal/unix/fn.signal.html create mode 100644 actix_rt/signal/unix/index.html create mode 100644 actix_rt/signal/unix/sidebar-items.js create mode 100644 actix_rt/signal/unix/struct.Signal.html create mode 100644 actix_rt/signal/unix/struct.SignalKind.html create mode 100644 actix_rt/struct.Arbiter.html create mode 100644 actix_rt/struct.ArbiterHandle.html create mode 100644 actix_rt/struct.Runtime.html create mode 100644 actix_rt/struct.System.html create mode 100644 actix_rt/struct.SystemRunner.html create mode 100644 actix_rt/system/struct.System.html create mode 100644 actix_rt/system/struct.SystemRunner.html create mode 100644 actix_rt/task/fn.spawn_blocking.html create mode 100644 actix_rt/task/fn.yield_now.html create mode 100644 actix_rt/task/index.html create mode 100644 actix_rt/task/sidebar-items.js create mode 100644 actix_rt/task/struct.JoinError.html create mode 100644 actix_rt/task/struct.JoinHandle.html create mode 100644 actix_rt/time/fn.interval.html create mode 100644 actix_rt/time/fn.interval_at.html create mode 100644 actix_rt/time/fn.sleep.html create mode 100644 actix_rt/time/fn.sleep_until.html create mode 100644 actix_rt/time/fn.timeout.html create mode 100644 actix_rt/time/index.html create mode 100644 actix_rt/time/sidebar-items.js create mode 100644 actix_rt/time/struct.Instant.html create mode 100644 actix_rt/time/struct.Interval.html create mode 100644 actix_rt/time/struct.Sleep.html create mode 100644 actix_rt/time/struct.Timeout.html create mode 100644 actix_server/all.html create mode 100644 actix_server/builder/enum.MpTcp.html create mode 100644 actix_server/builder/struct.ServerBuilder.html create mode 100644 actix_server/enum.MpTcp.html create mode 100644 actix_server/handle/struct.ServerHandle.html create mode 100644 actix_server/index.html create mode 100644 actix_server/server/struct.Server.html create mode 100644 actix_server/sidebar-items.js create mode 100644 actix_server/struct.Server.html create mode 100644 actix_server/struct.ServerBuilder.html create mode 100644 actix_server/struct.ServerHandle.html create mode 100644 actix_server/struct.TestServer.html create mode 100644 actix_server/test_server/struct.TestServer.html create mode 100644 actix_service/all.html create mode 100644 actix_service/apply/fn.apply_fn.html create mode 100644 actix_service/apply/fn.apply_fn_factory.html create mode 100644 actix_service/apply_cfg/fn.apply_cfg.html create mode 100644 actix_service/apply_cfg/fn.apply_cfg_factory.html create mode 100644 actix_service/boxed/fn.factory.html create mode 100644 actix_service/boxed/fn.rc_service.html create mode 100644 actix_service/boxed/fn.service.html create mode 100644 actix_service/boxed/index.html create mode 100644 actix_service/boxed/sidebar-items.js create mode 100644 actix_service/boxed/struct.BoxServiceFactory.html create mode 100644 actix_service/boxed/type.BoxFuture.html create mode 100644 actix_service/boxed/type.BoxService.html create mode 100644 actix_service/boxed/type.RcService.html create mode 100644 actix_service/ext/trait.ServiceExt.html create mode 100644 actix_service/ext/trait.ServiceFactoryExt.html create mode 100644 actix_service/ext/trait.TransformExt.html create mode 100644 actix_service/fn.apply.html create mode 100644 actix_service/fn.apply_cfg.html create mode 100644 actix_service/fn.apply_cfg_factory.html create mode 100644 actix_service/fn.apply_fn.html create mode 100644 actix_service/fn.apply_fn_factory.html create mode 100644 actix_service/fn.fn_factory.html create mode 100644 actix_service/fn.fn_factory_with_config.html create mode 100644 actix_service/fn.fn_service.html create mode 100644 actix_service/fn.into_service.html create mode 100644 actix_service/fn.map_config.html create mode 100644 actix_service/fn.unit_config.html create mode 100644 actix_service/fn_service/fn.fn_factory.html create mode 100644 actix_service/fn_service/fn.fn_factory_with_config.html create mode 100644 actix_service/fn_service/fn.fn_service.html create mode 100644 actix_service/index.html create mode 100644 actix_service/macro.always_ready!.html create mode 100644 actix_service/macro.always_ready.html create mode 100644 actix_service/macro.forward_ready!.html create mode 100644 actix_service/macro.forward_ready.html create mode 100644 actix_service/map_config/fn.map_config.html create mode 100644 actix_service/map_config/fn.unit_config.html create mode 100644 actix_service/sidebar-items.js create mode 100644 actix_service/struct.ApplyTransform.html create mode 100644 actix_service/trait.IntoService.html create mode 100644 actix_service/trait.IntoServiceFactory.html create mode 100644 actix_service/trait.Service.html create mode 100644 actix_service/trait.ServiceExt.html create mode 100644 actix_service/trait.ServiceFactory.html create mode 100644 actix_service/trait.ServiceFactoryExt.html create mode 100644 actix_service/trait.Transform.html create mode 100644 actix_service/trait.TransformExt.html create mode 100644 actix_service/transform/fn.apply.html create mode 100644 actix_service/transform/struct.ApplyTransform.html create mode 100644 actix_service/transform/trait.Transform.html create mode 100644 actix_tls/accept/enum.TlsError.html create mode 100644 actix_tls/accept/fn.max_concurrent_tls_connect.html create mode 100644 actix_tls/accept/index.html create mode 100644 actix_tls/accept/native_tls/index.html create mode 100644 actix_tls/accept/native_tls/reexports/index.html create mode 100644 actix_tls/accept/native_tls/reexports/sidebar-items.js create mode 100644 actix_tls/accept/native_tls/reexports/struct.Error.html create mode 100644 actix_tls/accept/native_tls/reexports/struct.TlsAcceptor.html create mode 100644 actix_tls/accept/native_tls/sidebar-items.js create mode 100644 actix_tls/accept/native_tls/struct.Acceptor.html create mode 100644 actix_tls/accept/native_tls/struct.AcceptorService.html create mode 100644 actix_tls/accept/native_tls/struct.TlsStream.html create mode 100644 actix_tls/accept/openssl/index.html create mode 100644 actix_tls/accept/openssl/reexports/enum.HandshakeError.html create mode 100644 actix_tls/accept/openssl/reexports/index.html create mode 100644 actix_tls/accept/openssl/reexports/sidebar-items.js create mode 100644 actix_tls/accept/openssl/reexports/struct.AlpnError.html create mode 100644 actix_tls/accept/openssl/reexports/struct.Error.html create mode 100644 actix_tls/accept/openssl/reexports/struct.Ssl.html create mode 100644 actix_tls/accept/openssl/reexports/struct.SslAcceptor.html create mode 100644 actix_tls/accept/openssl/reexports/struct.SslAcceptorBuilder.html create mode 100644 actix_tls/accept/openssl/sidebar-items.js create mode 100644 actix_tls/accept/openssl/struct.Acceptor.html create mode 100644 actix_tls/accept/openssl/struct.AcceptorService.html create mode 100644 actix_tls/accept/openssl/struct.TlsStream.html create mode 100644 actix_tls/accept/rustls_0_20/index.html create mode 100644 actix_tls/accept/rustls_0_20/reexports/index.html create mode 100644 actix_tls/accept/rustls_0_20/reexports/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_20/reexports/struct.ServerConfig.html create mode 100644 actix_tls/accept/rustls_0_20/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_20/struct.Acceptor.html create mode 100644 actix_tls/accept/rustls_0_20/struct.AcceptorService.html create mode 100644 actix_tls/accept/rustls_0_20/struct.TlsStream.html create mode 100644 actix_tls/accept/rustls_0_21/index.html create mode 100644 actix_tls/accept/rustls_0_21/reexports/index.html create mode 100644 actix_tls/accept/rustls_0_21/reexports/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_21/reexports/struct.ServerConfig.html create mode 100644 actix_tls/accept/rustls_0_21/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_21/struct.Acceptor.html create mode 100644 actix_tls/accept/rustls_0_21/struct.AcceptorService.html create mode 100644 actix_tls/accept/rustls_0_21/struct.TlsStream.html create mode 100644 actix_tls/accept/rustls_0_22/index.html create mode 100644 actix_tls/accept/rustls_0_22/reexports/index.html create mode 100644 actix_tls/accept/rustls_0_22/reexports/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_22/reexports/struct.ServerConfig.html create mode 100644 actix_tls/accept/rustls_0_22/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_22/struct.Acceptor.html create mode 100644 actix_tls/accept/rustls_0_22/struct.AcceptorService.html create mode 100644 actix_tls/accept/rustls_0_22/struct.TlsStream.html create mode 100644 actix_tls/accept/rustls_0_23/index.html create mode 100644 actix_tls/accept/rustls_0_23/reexports/index.html create mode 100644 actix_tls/accept/rustls_0_23/reexports/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_23/reexports/struct.ServerConfig.html create mode 100644 actix_tls/accept/rustls_0_23/sidebar-items.js create mode 100644 actix_tls/accept/rustls_0_23/struct.Acceptor.html create mode 100644 actix_tls/accept/rustls_0_23/struct.AcceptorService.html create mode 100644 actix_tls/accept/rustls_0_23/struct.TlsStream.html create mode 100644 actix_tls/accept/sidebar-items.js create mode 100644 actix_tls/all.html create mode 100644 actix_tls/connect/connection/struct.Connection.html create mode 100644 actix_tls/connect/connector/struct.Connector.html create mode 100644 actix_tls/connect/connector/struct.ConnectorService.html create mode 100644 actix_tls/connect/enum.ConnectError.html create mode 100644 actix_tls/connect/error/enum.ConnectError.html create mode 100644 actix_tls/connect/host/trait.Host.html create mode 100644 actix_tls/connect/index.html create mode 100644 actix_tls/connect/info/struct.ConnectInfo.html create mode 100644 actix_tls/connect/native_tls/index.html create mode 100644 actix_tls/connect/native_tls/reexports/index.html create mode 100644 actix_tls/connect/native_tls/reexports/sidebar-items.js create mode 100644 actix_tls/connect/native_tls/reexports/struct.AsyncTlsStream.html create mode 100644 actix_tls/connect/native_tls/reexports/struct.TlsConnector.html create mode 100644 actix_tls/connect/native_tls/sidebar-items.js create mode 100644 actix_tls/connect/native_tls/struct.TlsConnector.html create mode 100644 actix_tls/connect/openssl/index.html create mode 100644 actix_tls/connect/openssl/reexports/enum.HandshakeError.html create mode 100644 actix_tls/connect/openssl/reexports/index.html create mode 100644 actix_tls/connect/openssl/reexports/sidebar-items.js create mode 100644 actix_tls/connect/openssl/reexports/struct.AsyncSslStream.html create mode 100644 actix_tls/connect/openssl/reexports/struct.Error.html create mode 100644 actix_tls/connect/openssl/reexports/struct.SslConnector.html create mode 100644 actix_tls/connect/openssl/reexports/struct.SslConnectorBuilder.html create mode 100644 actix_tls/connect/openssl/reexports/struct.SslMethod.html create mode 100644 actix_tls/connect/openssl/sidebar-items.js create mode 100644 actix_tls/connect/openssl/struct.TlsConnector.html create mode 100644 actix_tls/connect/openssl/struct.TlsConnectorService.html create mode 100644 actix_tls/connect/resolve/trait.Resolve.html create mode 100644 actix_tls/connect/resolver/struct.Resolver.html create mode 100644 actix_tls/connect/resolver/struct.ResolverService.html create mode 100644 actix_tls/connect/rustls_0_20/fn.native_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_20/fn.webpki_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_20/index.html create mode 100644 actix_tls/connect/rustls_0_20/reexports/index.html create mode 100644 actix_tls/connect/rustls_0_20/reexports/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_20/reexports/static.TLS_SERVER_ROOTS.html create mode 100644 actix_tls/connect/rustls_0_20/reexports/struct.AsyncTlsStream.html create mode 100644 actix_tls/connect/rustls_0_20/reexports/struct.ClientConfig.html create mode 100644 actix_tls/connect/rustls_0_20/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_20/struct.TlsConnector.html create mode 100644 actix_tls/connect/rustls_0_20/struct.TlsConnectorService.html create mode 100644 actix_tls/connect/rustls_0_21/fn.native_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_21/fn.webpki_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_21/index.html create mode 100644 actix_tls/connect/rustls_0_21/reexports/constant.TLS_SERVER_ROOTS.html create mode 100644 actix_tls/connect/rustls_0_21/reexports/index.html create mode 100644 actix_tls/connect/rustls_0_21/reexports/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_21/reexports/struct.AsyncTlsStream.html create mode 100644 actix_tls/connect/rustls_0_21/reexports/struct.ClientConfig.html create mode 100644 actix_tls/connect/rustls_0_21/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_21/struct.TlsConnector.html create mode 100644 actix_tls/connect/rustls_0_21/struct.TlsConnectorService.html create mode 100644 actix_tls/connect/rustls_0_22/fn.native_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_22/fn.webpki_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_22/index.html create mode 100644 actix_tls/connect/rustls_0_22/reexports/constant.TLS_SERVER_ROOTS.html create mode 100644 actix_tls/connect/rustls_0_22/reexports/index.html create mode 100644 actix_tls/connect/rustls_0_22/reexports/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_22/reexports/struct.AsyncTlsStream.html create mode 100644 actix_tls/connect/rustls_0_22/reexports/struct.ClientConfig.html create mode 100644 actix_tls/connect/rustls_0_22/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_22/struct.TlsConnector.html create mode 100644 actix_tls/connect/rustls_0_22/struct.TlsConnectorService.html create mode 100644 actix_tls/connect/rustls_0_23/fn.native_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_23/fn.webpki_roots_cert_store.html create mode 100644 actix_tls/connect/rustls_0_23/index.html create mode 100644 actix_tls/connect/rustls_0_23/reexports/constant.TLS_SERVER_ROOTS.html create mode 100644 actix_tls/connect/rustls_0_23/reexports/index.html create mode 100644 actix_tls/connect/rustls_0_23/reexports/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_23/reexports/struct.AsyncTlsStream.html create mode 100644 actix_tls/connect/rustls_0_23/reexports/struct.ClientConfig.html create mode 100644 actix_tls/connect/rustls_0_23/sidebar-items.js create mode 100644 actix_tls/connect/rustls_0_23/struct.TlsConnector.html create mode 100644 actix_tls/connect/rustls_0_23/struct.TlsConnectorService.html create mode 100644 actix_tls/connect/sidebar-items.js create mode 100644 actix_tls/connect/struct.ConnectInfo.html create mode 100644 actix_tls/connect/struct.Connection.html create mode 100644 actix_tls/connect/struct.Connector.html create mode 100644 actix_tls/connect/struct.ConnectorService.html create mode 100644 actix_tls/connect/struct.Resolver.html create mode 100644 actix_tls/connect/struct.ResolverService.html create mode 100644 actix_tls/connect/tcp/index.html create mode 100644 actix_tls/connect/tcp/sidebar-items.js create mode 100644 actix_tls/connect/tcp/struct.TcpConnector.html create mode 100644 actix_tls/connect/tcp/struct.TcpConnectorService.html create mode 100644 actix_tls/connect/trait.Host.html create mode 100644 actix_tls/connect/trait.Resolve.html create mode 100644 actix_tls/index.html create mode 100644 actix_tls/sidebar-items.js create mode 100644 actix_tracing/all.html create mode 100644 actix_tracing/fn.trace.html create mode 100644 actix_tracing/index.html create mode 100644 actix_tracing/sidebar-items.js create mode 100644 actix_tracing/struct.TracingService.html create mode 100644 actix_tracing/struct.TracingTransform.html create mode 100644 actix_utils/all.html create mode 100644 actix_utils/counter/index.html create mode 100644 actix_utils/counter/sidebar-items.js create mode 100644 actix_utils/counter/struct.Counter.html create mode 100644 actix_utils/counter/struct.CounterGuard.html create mode 100644 actix_utils/future/either/enum.Either.html create mode 100644 actix_utils/future/enum.Either.html create mode 100644 actix_utils/future/fn.err.html create mode 100644 actix_utils/future/fn.ok.html create mode 100644 actix_utils/future/fn.poll_fn.html create mode 100644 actix_utils/future/fn.ready.html create mode 100644 actix_utils/future/index.html create mode 100644 actix_utils/future/poll_fn/fn.poll_fn.html create mode 100644 actix_utils/future/poll_fn/struct.PollFn.html create mode 100644 actix_utils/future/ready/fn.err.html create mode 100644 actix_utils/future/ready/fn.ok.html create mode 100644 actix_utils/future/ready/fn.ready.html create mode 100644 actix_utils/future/ready/struct.Ready.html create mode 100644 actix_utils/future/sidebar-items.js create mode 100644 actix_utils/future/struct.PollFn.html create mode 100644 actix_utils/future/struct.Ready.html create mode 100644 actix_utils/index.html create mode 100644 actix_utils/sidebar-items.js create mode 100644 bytestring/all.html create mode 100644 bytestring/index.html create mode 100644 bytestring/sidebar-items.js create mode 100644 bytestring/struct.ByteString.html create mode 100644 crates.js create mode 100644 help.html create mode 100644 index.html create mode 100644 local_channel/all.html create mode 100644 local_channel/index.html create mode 100644 local_channel/mpsc/fn.channel.html create mode 100644 local_channel/mpsc/index.html create mode 100644 local_channel/mpsc/sidebar-items.js create mode 100644 local_channel/mpsc/struct.Receiver.html create mode 100644 local_channel/mpsc/struct.SendError.html create mode 100644 local_channel/mpsc/struct.Sender.html create mode 100644 local_channel/sidebar-items.js create mode 100644 local_waker/all.html create mode 100644 local_waker/index.html create mode 100644 local_waker/sidebar-items.js create mode 100644 local_waker/struct.LocalWaker.html create mode 100644 search-index.js create mode 100644 search.desc/actix_codec/actix_codec-desc-0-.js create mode 100644 search.desc/actix_macros/actix_macros-desc-0-.js create mode 100644 search.desc/actix_rt/actix_rt-desc-0-.js create mode 100644 search.desc/actix_server/actix_server-desc-0-.js create mode 100644 search.desc/actix_service/actix_service-desc-0-.js create mode 100644 search.desc/actix_tls/actix_tls-desc-0-.js create mode 100644 search.desc/actix_tracing/actix_tracing-desc-0-.js create mode 100644 search.desc/actix_utils/actix_utils-desc-0-.js create mode 100644 search.desc/bytestring/bytestring-desc-0-.js create mode 100644 search.desc/local_channel/local_channel-desc-0-.js create mode 100644 search.desc/local_waker/local_waker-desc-0-.js create mode 100644 settings.html create mode 100644 src-files.js create mode 100644 src/actix_codec/bcodec.rs.html create mode 100644 src/actix_codec/framed.rs.html create mode 100644 src/actix_codec/lib.rs.html create mode 100644 src/actix_codec/lines.rs.html create mode 100644 src/actix_macros/lib.rs.html create mode 100644 src/actix_rt/arbiter.rs.html create mode 100644 src/actix_rt/lib.rs.html create mode 100644 src/actix_rt/runtime.rs.html create mode 100644 src/actix_rt/system.rs.html create mode 100644 src/actix_server/accept.rs.html create mode 100644 src/actix_server/availability.rs.html create mode 100644 src/actix_server/builder.rs.html create mode 100644 src/actix_server/handle.rs.html create mode 100644 src/actix_server/join_all.rs.html create mode 100644 src/actix_server/lib.rs.html create mode 100644 src/actix_server/server.rs.html create mode 100644 src/actix_server/service.rs.html create mode 100644 src/actix_server/signals.rs.html create mode 100644 src/actix_server/socket.rs.html create mode 100644 src/actix_server/test_server.rs.html create mode 100644 src/actix_server/waker_queue.rs.html create mode 100644 src/actix_server/worker.rs.html create mode 100644 src/actix_service/and_then.rs.html create mode 100644 src/actix_service/apply.rs.html create mode 100644 src/actix_service/apply_cfg.rs.html create mode 100644 src/actix_service/boxed.rs.html create mode 100644 src/actix_service/ext.rs.html create mode 100644 src/actix_service/fn_service.rs.html create mode 100644 src/actix_service/lib.rs.html create mode 100644 src/actix_service/macros.rs.html create mode 100644 src/actix_service/map.rs.html create mode 100644 src/actix_service/map_config.rs.html create mode 100644 src/actix_service/map_err.rs.html create mode 100644 src/actix_service/map_init_err.rs.html create mode 100644 src/actix_service/pipeline.rs.html create mode 100644 src/actix_service/ready.rs.html create mode 100644 src/actix_service/then.rs.html create mode 100644 src/actix_service/transform.rs.html create mode 100644 src/actix_service/transform_err.rs.html create mode 100644 src/actix_tls/accept/mod.rs.html create mode 100644 src/actix_tls/accept/native_tls.rs.html create mode 100644 src/actix_tls/accept/openssl.rs.html create mode 100644 src/actix_tls/accept/rustls_0_20.rs.html create mode 100644 src/actix_tls/accept/rustls_0_21.rs.html create mode 100644 src/actix_tls/accept/rustls_0_22.rs.html create mode 100644 src/actix_tls/accept/rustls_0_23.rs.html create mode 100644 src/actix_tls/connect/connect_addrs.rs.html create mode 100644 src/actix_tls/connect/connection.rs.html create mode 100644 src/actix_tls/connect/connector.rs.html create mode 100644 src/actix_tls/connect/error.rs.html create mode 100644 src/actix_tls/connect/host.rs.html create mode 100644 src/actix_tls/connect/info.rs.html create mode 100644 src/actix_tls/connect/mod.rs.html create mode 100644 src/actix_tls/connect/native_tls.rs.html create mode 100644 src/actix_tls/connect/openssl.rs.html create mode 100644 src/actix_tls/connect/resolve.rs.html create mode 100644 src/actix_tls/connect/resolver.rs.html create mode 100644 src/actix_tls/connect/rustls_0_20.rs.html create mode 100644 src/actix_tls/connect/rustls_0_21.rs.html create mode 100644 src/actix_tls/connect/rustls_0_22.rs.html create mode 100644 src/actix_tls/connect/rustls_0_23.rs.html create mode 100644 src/actix_tls/connect/tcp.rs.html create mode 100644 src/actix_tls/connect/uri.rs.html create mode 100644 src/actix_tls/lib.rs.html create mode 100644 src/actix_tracing/lib.rs.html create mode 100644 src/actix_utils/counter.rs.html create mode 100644 src/actix_utils/future/either.rs.html create mode 100644 src/actix_utils/future/mod.rs.html create mode 100644 src/actix_utils/future/poll_fn.rs.html create mode 100644 src/actix_utils/future/ready.rs.html create mode 100644 src/actix_utils/lib.rs.html create mode 100644 src/bytestring/lib.rs.html create mode 100644 src/local_channel/lib.rs.html create mode 100644 src/local_channel/mpsc.rs.html create mode 100644 src/local_waker/lib.rs.html create mode 100644 static.files/COPYRIGHT-23e9bde6c69aea69.txt create mode 100644 static.files/FiraSans-LICENSE-db4b642586e02d97.txt create mode 100644 static.files/FiraSans-Medium-8f9a781e4970d388.woff2 create mode 100644 static.files/FiraSans-Regular-018c141bf0843ffd.woff2 create mode 100644 static.files/LICENSE-APACHE-b91fa81cba47b86a.txt create mode 100644 static.files/LICENSE-MIT-65090b722b3f6c56.txt create mode 100644 static.files/NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2 create mode 100644 static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt create mode 100644 static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 create mode 100644 static.files/SourceCodePro-LICENSE-d180d465a756484a.txt create mode 100644 static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 create mode 100644 static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2 create mode 100644 static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 create mode 100644 static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 create mode 100644 static.files/SourceSerif4-LICENSE-3bb119e13b1258b7.md create mode 100644 static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 create mode 100644 static.files/favicon-2c020d218678b618.svg create mode 100644 static.files/favicon-32x32-422f7d1d52889060.png create mode 100644 static.files/main-54bc299d2a5e4e43.js create mode 100644 static.files/normalize-76eba96aa4d2e634.css create mode 100644 static.files/noscript-0111fcff984fae8f.css create mode 100644 static.files/rust-logo-151179464ae7ed46.svg create mode 100644 static.files/rustdoc-b778ab399e080a4b.css create mode 100644 static.files/scrape-examples-46fc985aa763a438.js create mode 100644 static.files/search-e056c65ede92db13.js create mode 100644 static.files/settings-805db61a62df4bd2.js create mode 100644 static.files/src-script-e66d777a5a92e9b2.js create mode 100644 static.files/storage-1d39b6787ed640ff.js create mode 100644 trait.impl/actix_service/ext/trait.ServiceExt.js create mode 100644 trait.impl/actix_service/ext/trait.ServiceFactoryExt.js create mode 100644 trait.impl/actix_service/ext/trait.TransformExt.js create mode 100644 trait.impl/actix_service/trait.IntoService.js create mode 100644 trait.impl/actix_service/trait.IntoServiceFactory.js create mode 100644 trait.impl/actix_service/trait.Service.js create mode 100644 trait.impl/actix_service/trait.ServiceFactory.js create mode 100644 trait.impl/actix_service/transform/trait.Transform.js create mode 100644 trait.impl/actix_tls/connect/host/trait.Host.js create mode 100644 trait.impl/core/borrow/trait.Borrow.js create mode 100644 trait.impl/core/clone/trait.Clone.js create mode 100644 trait.impl/core/cmp/trait.Eq.js create mode 100644 trait.impl/core/cmp/trait.Ord.js create mode 100644 trait.impl/core/cmp/trait.PartialEq.js create mode 100644 trait.impl/core/cmp/trait.PartialOrd.js create mode 100644 trait.impl/core/convert/trait.AsRef.js create mode 100644 trait.impl/core/convert/trait.From.js create mode 100644 trait.impl/core/convert/trait.TryFrom.js create mode 100644 trait.impl/core/default/trait.Default.js create mode 100644 trait.impl/core/error/trait.Error.js create mode 100644 trait.impl/core/fmt/trait.Debug.js create mode 100644 trait.impl/core/fmt/trait.Display.js create mode 100644 trait.impl/core/future/future/trait.Future.js create mode 100644 trait.impl/core/hash/trait.Hash.js create mode 100644 trait.impl/core/marker/trait.Copy.js create mode 100644 trait.impl/core/marker/trait.Freeze.js create mode 100644 trait.impl/core/marker/trait.Send.js create mode 100644 trait.impl/core/marker/trait.StructuralPartialEq.js create mode 100644 trait.impl/core/marker/trait.Sync.js create mode 100644 trait.impl/core/marker/trait.Unpin.js create mode 100644 trait.impl/core/ops/deref/trait.Deref.js create mode 100644 trait.impl/core/ops/deref/trait.DerefMut.js create mode 100644 trait.impl/core/ops/drop/trait.Drop.js create mode 100644 trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js create mode 100644 trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js create mode 100644 trait.impl/futures_core/stream/trait.Stream.js create mode 100644 trait.impl/futures_sink/trait.Sink.js create mode 100644 trait.impl/serde/de/trait.Deserialize.js create mode 100644 trait.impl/serde/ser/trait.Serialize.js create mode 100644 trait.impl/tokio/io/async_read/trait.AsyncRead.js create mode 100644 trait.impl/tokio/io/async_write/trait.AsyncWrite.js create mode 100644 trait.impl/tokio_util/codec/decoder/trait.Decoder.js create mode 100644 trait.impl/tokio_util/codec/encoder/trait.Encoder.js create mode 100644 type.impl/alloc/boxed/struct.Box.js create mode 100644 type.impl/alloc/rc/struct.Rc.js create mode 100644 type.impl/core/pin/struct.Pin.js diff --git a/.lock b/.lock new file mode 100644 index 00000000..e69de29b diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/actix_codec/all.html b/actix_codec/all.html new file mode 100644 index 00000000..700f0ac0 --- /dev/null +++ b/actix_codec/all.html @@ -0,0 +1 @@ +List of all items in this crate
\ No newline at end of file diff --git a/actix_codec/bcodec/struct.BytesCodec.html b/actix_codec/bcodec/struct.BytesCodec.html new file mode 100644 index 00000000..617b3cac --- /dev/null +++ b/actix_codec/bcodec/struct.BytesCodec.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_codec/struct.BytesCodec.html...

+ + + \ No newline at end of file diff --git a/actix_codec/fn.poll_read_buf.html b/actix_codec/fn.poll_read_buf.html new file mode 100644 index 00000000..2bb2fc56 --- /dev/null +++ b/actix_codec/fn.poll_read_buf.html @@ -0,0 +1,35 @@ +poll_read_buf in actix_codec - Rust
actix_codec

Function poll_read_buf

pub fn poll_read_buf<T, B>(
+    io: Pin<&mut T>,
+    cx: &mut Context<'_>,
+    buf: &mut B,
+) -> Poll<Result<usize, Error>>
where + T: AsyncRead + ?Sized, + B: BufMut,
Expand description

Try to read data from an AsyncRead into an implementer of the BufMut trait.

+

§Example

+
use bytes::{Bytes, BytesMut};
+use tokio_stream as stream;
+use tokio::io::Result;
+use tokio_util::io::{StreamReader, poll_read_buf};
+use futures::future::poll_fn;
+use std::pin::Pin;
+
+// Create a reader from an iterator. This particular reader will always be
+// ready.
+let mut read = StreamReader::new(stream::iter(vec![Result::Ok(Bytes::from_static(&[0, 1, 2, 3]))]));
+
+let mut buf = BytesMut::new();
+let mut reads = 0;
+
+loop {
+    reads += 1;
+    let n = poll_fn(|cx| poll_read_buf(Pin::new(&mut read), cx, &mut buf)).await?;
+
+    if n == 0 {
+        break;
+    }
+}
+
+// one or more reads might be necessary.
+assert!(reads >= 1);
+assert_eq!(&buf[..], &[0, 1, 2, 3]);
+
\ No newline at end of file diff --git a/actix_codec/framed/struct.Framed.html b/actix_codec/framed/struct.Framed.html new file mode 100644 index 00000000..57d68330 --- /dev/null +++ b/actix_codec/framed/struct.Framed.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_codec/struct.Framed.html...

+ + + \ No newline at end of file diff --git a/actix_codec/framed/struct.FramedParts.html b/actix_codec/framed/struct.FramedParts.html new file mode 100644 index 00000000..5514d76b --- /dev/null +++ b/actix_codec/framed/struct.FramedParts.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_codec/struct.FramedParts.html...

+ + + \ No newline at end of file diff --git a/actix_codec/index.html b/actix_codec/index.html new file mode 100644 index 00000000..b8f7b368 --- /dev/null +++ b/actix_codec/index.html @@ -0,0 +1,6 @@ +actix_codec - Rust

Crate actix_codec

source
Expand description

Codec utilities for working with framed protocols.

+

Contains adapters to go from streams of bytes, AsyncRead and AsyncWrite, to framed +streams implementing Sink and Stream. Framed streams are also known as transports.

+

Structs§

  • Bytes codec. Reads/writes chunks of bytes from a stream.
  • A unified Stream and Sink interface to an underlying I/O object, using the Encoder and +Decoder traits to encode and decode frames.
  • FramedParts contains an export of the data of a Framed transport.
  • Lines codec. Reads/writes line delimited strings.
  • A wrapper around a byte buffer that is incrementally filled and initialized.

Traits§

Functions§

\ No newline at end of file diff --git a/actix_codec/lines/struct.LinesCodec.html b/actix_codec/lines/struct.LinesCodec.html new file mode 100644 index 00000000..f694bbc4 --- /dev/null +++ b/actix_codec/lines/struct.LinesCodec.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_codec/struct.LinesCodec.html...

+ + + \ No newline at end of file diff --git a/actix_codec/sidebar-items.js b/actix_codec/sidebar-items.js new file mode 100644 index 00000000..ada95f74 --- /dev/null +++ b/actix_codec/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["poll_read_buf"],"struct":["BytesCodec","Framed","FramedParts","LinesCodec","ReadBuf"],"trait":["AsyncRead","AsyncWrite","Decoder","Encoder"]}; \ No newline at end of file diff --git a/actix_codec/struct.BytesCodec.html b/actix_codec/struct.BytesCodec.html new file mode 100644 index 00000000..8b5dda32 --- /dev/null +++ b/actix_codec/struct.BytesCodec.html @@ -0,0 +1,29 @@ +BytesCodec in actix_codec - Rust
actix_codec

Struct BytesCodec

source
pub struct BytesCodec;
Expand description

Bytes codec. Reads/writes chunks of bytes from a stream.

+

Trait Implementations§

source§

impl Clone for BytesCodec

source§

fn clone(&self) -> BytesCodec

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BytesCodec

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Decoder for BytesCodec

source§

type Item = BytesMut

The type of decoded frames.
source§

type Error = Error

The type of unrecoverable frame decoding errors. Read more
source§

fn decode( + &mut self, + src: &mut BytesMut, +) -> Result<Option<Self::Item>, Self::Error>

Attempts to decode a frame from the provided buffer of bytes. Read more
§

fn decode_eof( + &mut self, + buf: &mut BytesMut, +) -> Result<Option<Self::Item>, Self::Error>

A default method available to be called when there are no more bytes +available to be read from the underlying I/O. Read more
§

fn framed<T>(self, io: T) -> Framed<T, Self>
where + T: AsyncRead + AsyncWrite, + Self: Sized,

Provides a Stream and Sink interface for reading and writing to this +Io object, using Decode and Encode to read and write the raw data. Read more
source§

impl Encoder<Bytes> for BytesCodec

source§

type Error = Error

The type of encoding errors. Read more
source§

fn encode(&mut self, item: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error>

Encodes a frame into the buffer provided. Read more
source§

impl Copy for BytesCodec

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_codec/struct.Framed.html b/actix_codec/struct.Framed.html new file mode 100644 index 00000000..07551d3f --- /dev/null +++ b/actix_codec/struct.Framed.html @@ -0,0 +1,117 @@ +Framed in actix_codec - Rust
actix_codec

Struct Framed

source
pub struct Framed<T, U> { /* private fields */ }
Expand description

A unified Stream and Sink interface to an underlying I/O object, using the Encoder and +Decoder traits to encode and decode frames.

+

Raw I/O objects work with byte sequences, but higher-level code usually wants to batch these +into meaningful chunks, called “frames”. This method layers framing on top of an I/O object, +by using the Encoder/Decoder traits to handle encoding and decoding of message frames. +Note that the incoming and outgoing frame types may be distinct.

+

Implementations§

source§

impl<T, U> Framed<T, U>
where + T: AsyncRead + AsyncWrite, + U: Decoder,

source

pub fn new(io: T, codec: U) -> Framed<T, U>

This function returns a single object that is both Stream and Sink; grouping this into +a single object is often useful for layering things like gzip or TLS, which require both +read and write access to the underlying object.

+
source§

impl<T, U> Framed<T, U>

source

pub fn codec_ref(&self) -> &U

Returns a reference to the underlying codec.

+
source

pub fn codec_mut(&mut self) -> &mut U

Returns a mutable reference to the underlying codec.

+
source

pub fn io_ref(&self) -> &T

Returns a reference to the underlying I/O stream wrapped by Frame.

+

Note that care should be taken to not tamper with the underlying stream of data coming in as +it may corrupt the stream of frames otherwise being worked with.

+
source

pub fn io_mut(&mut self) -> &mut T

Returns a mutable reference to the underlying I/O stream.

+

Note that care should be taken to not tamper with the underlying stream of data coming in as +it may corrupt the stream of frames otherwise being worked with.

+
source

pub fn io_pin(self: Pin<&mut Self>) -> Pin<&mut T>

Returns a Pin of a mutable reference to the underlying I/O stream.

+
source

pub fn is_read_buf_empty(&self) -> bool

Check if read buffer is empty.

+
source

pub fn is_write_buf_empty(&self) -> bool

Check if write buffer is empty.

+
source

pub fn is_write_buf_full(&self) -> bool

Check if write buffer is full.

+
source

pub fn is_write_ready(&self) -> bool

Check if framed is able to write more data.

+

Framed object considers ready if there is free space in write buffer.

+
source

pub fn replace_codec<U2>(self, codec: U2) -> Framed<T, U2>

Consume the Frame, returning Frame with different codec.

+
source

pub fn into_map_io<F, T2>(self, f: F) -> Framed<T2, U>
where + F: Fn(T) -> T2,

Consume the Frame, returning Frame with different io.

+
source

pub fn into_map_codec<F, U2>(self, f: F) -> Framed<T, U2>
where + F: Fn(U) -> U2,

Consume the Frame, returning Frame with different codec.

+
source§

impl<T, U> Framed<T, U>

source

pub fn write<I>( + self: Pin<&mut Self>, + item: I, +) -> Result<(), <U as Encoder<I>>::Error>
where + T: AsyncWrite, + U: Encoder<I>,

Serialize item and write to the inner buffer

+
source

pub fn next_item( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Option<Result<<U as Decoder>::Item, U::Error>>>
where + T: AsyncRead, + U: Decoder,

Try to read underlying I/O stream and decode item.

+
source

pub fn flush<I>( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Result<(), U::Error>>
where + T: AsyncWrite, + U: Encoder<I>,

Flush write buffer to underlying I/O stream.

+
source

pub fn close<I>( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Result<(), U::Error>>
where + T: AsyncWrite, + U: Encoder<I>,

Flush write buffer and shutdown underlying I/O stream.

+
source§

impl<T, U> Framed<T, U>

source

pub fn from_parts(parts: FramedParts<T, U>) -> Framed<T, U>

This function returns a single object that is both Stream and Sink; grouping this into +a single object is often useful for layering things like gzip or TLS, which require both +read and write access to the underlying object.

+

These objects take a stream, a read buffer and a write buffer. These fields can be obtained +from an existing Framed with the into_parts method.

+
source

pub fn into_parts(self) -> FramedParts<T, U>

Consumes the Frame, returning its underlying I/O stream, the buffer with unprocessed data, +and the codec.

+

Note that care should be taken to not tamper with the underlying stream of data coming in as +it may corrupt the stream of frames otherwise being worked with.

+

Trait Implementations§

source§

impl<T, U> Debug for Framed<T, U>
where + T: Debug, + U: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T, U, I> Sink<I> for Framed<T, U>
where + T: AsyncWrite, + U: Encoder<I>, + U::Error: From<Error>,

source§

type Error = <U as Encoder<I>>::Error

The type of value produced by the sink when an error occurs.
source§

fn poll_ready( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Self::Error>>

Attempts to prepare the Sink to receive a value. Read more
source§

fn start_send(self: Pin<&mut Self>, item: I) -> Result<(), Self::Error>

Begin the process of sending a value to the sink. +Each call to this function must be preceded by a successful call to +poll_ready which returned Poll::Ready(Ok(())). Read more
source§

fn poll_flush( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Self::Error>>

Flush any remaining output from this sink. Read more
source§

fn poll_close( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Self::Error>>

Flush any remaining output and close this sink, if necessary. Read more
source§

impl<T, U> Stream for Framed<T, U>
where + T: AsyncRead, + U: Decoder,

source§

type Item = Result<<U as Decoder>::Item, <U as Decoder>::Error>

Values yielded by the stream.
source§

fn poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Option<Self::Item>>

Attempt to pull out the next value of this stream, registering the +current task for wakeup if the value is not yet available, and returning +None if the stream is exhausted. Read more
§

fn size_hint(&self) -> (usize, Option<usize>)

Returns the bounds on the remaining length of the stream. Read more
source§

impl<'__pin, T, U> Unpin for Framed<T, U>
where + __Origin<'__pin, T, U>: Unpin,

Auto Trait Implementations§

§

impl<T, U> Freeze for Framed<T, U>
where + T: Freeze, + U: Freeze,

§

impl<T, U> RefUnwindSafe for Framed<T, U>
where + T: RefUnwindSafe, + U: RefUnwindSafe,

§

impl<T, U> Send for Framed<T, U>
where + T: Send, + U: Send,

§

impl<T, U> Sync for Framed<T, U>
where + T: Sync, + U: Sync,

§

impl<T, U> UnwindSafe for Framed<T, U>
where + T: UnwindSafe, + U: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<S, T, E> TryStream for S
where + S: Stream<Item = Result<T, E>> + ?Sized,

§

type Ok = T

The type of successful values yielded by this future
§

type Error = E

The type of failures yielded by this future
§

fn try_poll_next( + self: Pin<&mut S>, + cx: &mut Context<'_>, +) -> Poll<Option<Result<<S as TryStream>::Ok, <S as TryStream>::Error>>>

Poll this TryStream as if it were a Stream. Read more
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_codec/struct.FramedParts.html b/actix_codec/struct.FramedParts.html new file mode 100644 index 00000000..2875a077 --- /dev/null +++ b/actix_codec/struct.FramedParts.html @@ -0,0 +1,43 @@ +FramedParts in actix_codec - Rust
actix_codec

Struct FramedParts

source
pub struct FramedParts<T, U> {
+    pub io: T,
+    pub codec: U,
+    pub read_buf: BytesMut,
+    pub write_buf: BytesMut,
+    /* private fields */
+}
Expand description

FramedParts contains an export of the data of a Framed transport.

+

It can be used to construct a new Framed with a different codec. It contains all current +buffers and the inner transport.

+

Fields§

§io: T

The inner transport used to read bytes to and write bytes to.

+
§codec: U

The codec object.

+
§read_buf: BytesMut

The buffer with read but unprocessed data.

+
§write_buf: BytesMut

A buffer with unprocessed data which are not written yet.

+

Implementations§

source§

impl<T, U> FramedParts<T, U>

source

pub fn new(io: T, codec: U) -> FramedParts<T, U>

Creates a new default FramedParts.

+
source

pub fn with_read_buf(io: T, codec: U, read_buf: BytesMut) -> FramedParts<T, U>

Creates a new FramedParts with read buffer.

+

Trait Implementations§

source§

impl<T: Debug, U: Debug> Debug for FramedParts<T, U>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T, U> Freeze for FramedParts<T, U>
where + T: Freeze, + U: Freeze,

§

impl<T, U> RefUnwindSafe for FramedParts<T, U>
where + T: RefUnwindSafe, + U: RefUnwindSafe,

§

impl<T, U> Send for FramedParts<T, U>
where + T: Send, + U: Send,

§

impl<T, U> Sync for FramedParts<T, U>
where + T: Sync, + U: Sync,

§

impl<T, U> Unpin for FramedParts<T, U>
where + T: Unpin, + U: Unpin,

§

impl<T, U> UnwindSafe for FramedParts<T, U>
where + T: UnwindSafe, + U: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_codec/struct.LinesCodec.html b/actix_codec/struct.LinesCodec.html new file mode 100644 index 00000000..11ae9c91 --- /dev/null +++ b/actix_codec/struct.LinesCodec.html @@ -0,0 +1,31 @@ +LinesCodec in actix_codec - Rust
actix_codec

Struct LinesCodec

source
#[non_exhaustive]
pub struct LinesCodec;
Expand description

Lines codec. Reads/writes line delimited strings.

+

Will split input up by LF or CRLF delimiters. Carriage return characters at the end of lines are +not preserved.

+

Trait Implementations§

source§

impl Clone for LinesCodec

source§

fn clone(&self) -> LinesCodec

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for LinesCodec

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Decoder for LinesCodec

source§

type Item = String

The type of decoded frames.
source§

type Error = Error

The type of unrecoverable frame decoding errors. Read more
source§

fn decode( + &mut self, + src: &mut BytesMut, +) -> Result<Option<Self::Item>, Self::Error>

Attempts to decode a frame from the provided buffer of bytes. Read more
source§

fn decode_eof( + &mut self, + src: &mut BytesMut, +) -> Result<Option<Self::Item>, Self::Error>

A default method available to be called when there are no more bytes +available to be read from the underlying I/O. Read more
§

fn framed<T>(self, io: T) -> Framed<T, Self>
where + T: AsyncRead + AsyncWrite, + Self: Sized,

Provides a Stream and Sink interface for reading and writing to this +Io object, using Decode and Encode to read and write the raw data. Read more
source§

impl Default for LinesCodec

source§

fn default() -> LinesCodec

Returns the “default value” for a type. Read more
source§

impl<T: AsRef<str>> Encoder<T> for LinesCodec

source§

type Error = Error

The type of encoding errors. Read more
source§

fn encode(&mut self, item: T, dst: &mut BytesMut) -> Result<(), Self::Error>

Encodes a frame into the buffer provided. Read more
source§

impl Copy for LinesCodec

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_codec/struct.ReadBuf.html b/actix_codec/struct.ReadBuf.html new file mode 100644 index 00000000..a4e6b39c --- /dev/null +++ b/actix_codec/struct.ReadBuf.html @@ -0,0 +1,83 @@ +ReadBuf in actix_codec - Rust
actix_codec

Struct ReadBuf

pub struct ReadBuf<'a> { /* private fields */ }
Expand description

A wrapper around a byte buffer that is incrementally filled and initialized.

+

This type is a sort of “double cursor”. It tracks three regions in the +buffer: a region at the beginning of the buffer that has been logically +filled with data, a region that has been initialized at some point but not +yet logically filled, and a region at the end that may be uninitialized. +The filled region is guaranteed to be a subset of the initialized region.

+

In summary, the contents of the buffer can be visualized as:

+
[             capacity              ]
+[ filled |         unfilled         ]
+[    initialized    | uninitialized ]
+

It is undefined behavior to de-initialize any bytes from the uninitialized +region, since it is merely unknown whether this region is uninitialized or +not, and if part of it turns out to be initialized, it must stay initialized.

+

Implementations§

§

impl<'a> ReadBuf<'a>

pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a>

Creates a new ReadBuf from a fully initialized buffer.

+

pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a>

Creates a new ReadBuf from a fully uninitialized buffer.

+

Use assume_init if part of the buffer is known to be already initialized.

+

pub fn capacity(&self) -> usize

Returns the total capacity of the buffer.

+

pub fn filled(&self) -> &[u8]

Returns a shared reference to the filled portion of the buffer.

+

pub fn filled_mut(&mut self) -> &mut [u8]

Returns a mutable reference to the filled portion of the buffer.

+

pub fn take(&mut self, n: usize) -> ReadBuf<'_>

Returns a new ReadBuf comprised of the unfilled section up to n.

+

pub fn initialized(&self) -> &[u8]

Returns a shared reference to the initialized portion of the buffer.

+

This includes the filled portion.

+

pub fn initialized_mut(&mut self) -> &mut [u8]

Returns a mutable reference to the initialized portion of the buffer.

+

This includes the filled portion.

+

pub unsafe fn inner_mut(&mut self) -> &mut [MaybeUninit<u8>]

Returns a mutable reference to the entire buffer, without ensuring that it has been fully +initialized.

+

The elements between 0 and self.filled().len() are filled, and those between 0 and +self.initialized().len() are initialized (and so can be converted to a &mut [u8]).

+

The caller of this method must ensure that these invariants are upheld. For example, if the +caller initializes some of the uninitialized section of the buffer, it must call +assume_init with the number of bytes initialized.

+
§Safety
+

The caller must not de-initialize portions of the buffer that have already been initialized. +This includes any bytes in the region marked as uninitialized by ReadBuf.

+

pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>]

Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully +initialized.

+
§Safety
+

The caller must not de-initialize portions of the buffer that have already been initialized. +This includes any bytes in the region marked as uninitialized by ReadBuf.

+

pub fn initialize_unfilled(&mut self) -> &mut [u8]

Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized.

+

Since ReadBuf tracks the region of the buffer that has been initialized, this is effectively “free” after +the first use.

+

pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8]

Returns a mutable reference to the first n bytes of the unfilled part of the buffer, ensuring it is +fully initialized.

+
§Panics
+

Panics if self.remaining() is less than n.

+

pub fn remaining(&self) -> usize

Returns the number of bytes at the end of the slice that have not yet been filled.

+

pub fn clear(&mut self)

Clears the buffer, resetting the filled region to empty.

+

The number of initialized bytes is not changed, and the contents of the buffer are not modified.

+

pub fn advance(&mut self, n: usize)

Advances the size of the filled region of the buffer.

+

The number of initialized bytes is not changed.

+
§Panics
+

Panics if the filled region of the buffer would become larger than the initialized region.

+

pub fn set_filled(&mut self, n: usize)

Sets the size of the filled region of the buffer.

+

The number of initialized bytes is not changed.

+

Note that this can be used to shrink the filled region of the buffer in addition to growing it (for +example, by a AsyncRead implementation that compresses data in-place).

+
§Panics
+

Panics if the filled region of the buffer would become larger than the initialized region.

+

pub unsafe fn assume_init(&mut self, n: usize)

Asserts that the first n unfilled bytes of the buffer are initialized.

+

ReadBuf assumes that bytes are never de-initialized, so this method does nothing when called with fewer +bytes than are already known to be initialized.

+
§Safety
+

The caller must ensure that n unfilled bytes of the buffer have already been initialized.

+

pub fn put_slice(&mut self, buf: &[u8])

Appends data to the buffer, advancing the written position and possibly also the initialized position.

+
§Panics
+

Panics if self.remaining() is less than buf.len().

+

Trait Implementations§

§

impl Debug for ReadBuf<'_>

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for ReadBuf<'a>

§

impl<'a> RefUnwindSafe for ReadBuf<'a>

§

impl<'a> Send for ReadBuf<'a>

§

impl<'a> Sync for ReadBuf<'a>

§

impl<'a> Unpin for ReadBuf<'a>

§

impl<'a> !UnwindSafe for ReadBuf<'a>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_codec/trait.AsyncRead.html b/actix_codec/trait.AsyncRead.html new file mode 100644 index 00000000..03c1d967 --- /dev/null +++ b/actix_codec/trait.AsyncRead.html @@ -0,0 +1,106 @@ +AsyncRead in actix_codec - Rust
actix_codec

Trait AsyncRead

pub trait AsyncRead {
+    // Required method
+    fn poll_read(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &mut ReadBuf<'_>,
+    ) -> Poll<Result<(), Error>>;
+}
Expand description

Reads bytes from a source.

+

This trait is analogous to the std::io::Read trait, but integrates with +the asynchronous task system. In particular, the poll_read method, +unlike Read::read, will automatically queue the current task for wakeup +and return if data is not yet available, rather than blocking the calling +thread.

+

Specifically, this means that the poll_read function will return one of +the following:

+
    +
  • +

    Poll::Ready(Ok(())) means that data was immediately read and placed into +the output buffer. The amount of data read can be determined by the +increase in the length of the slice returned by ReadBuf::filled. If the +difference is 0, either EOF has been reached, or the output buffer had zero +capacity (i.e. buf.remaining() == 0).

    +
  • +
  • +

    Poll::Pending means that no data was read into the buffer +provided. The I/O object is not currently readable but may become readable +in the future. Most importantly, the current future’s task is scheduled +to get unparked when the object is readable. This means that like +Future::poll you’ll receive a notification when the I/O object is +readable again.

    +
  • +
  • +

    Poll::Ready(Err(e)) for other errors are standard I/O errors coming from the +underlying object.

    +
  • +
+

This trait importantly means that the read method only works in the +context of a future’s task. The object may panic if used outside of a task.

+

Utilities for working with AsyncRead values are provided by +AsyncReadExt.

+

Required Methods§

fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf.

+

On success, returns Poll::Ready(Ok(())) and places data in the +unfilled portion of buf. If no data was read (buf.filled().len() is +unchanged), it implies that EOF has been reached.

+

If no data is available for reading, the method returns Poll::Pending +and arranges for the current task (via cx.waker()) to receive a +notification when the object becomes readable or is closed.

+

Implementations on Foreign Types§

§

impl AsyncRead for &[u8]

§

fn poll_read( + self: Pin<&mut &[u8]>, + _cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<L, R> AsyncRead for Either<L, R>
where + L: AsyncRead, + R: AsyncRead,

§

fn poll_read( + self: Pin<&mut Either<L, R>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<P> AsyncRead for Pin<P>
where + P: DerefMut + Unpin, + <P as Deref>::Target: AsyncRead,

§

fn poll_read( + self: Pin<&mut Pin<P>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<R, F> AsyncRead for InspectReader<R, F>
where + R: AsyncRead, + F: FnMut(&[u8]),

§

fn poll_read( + self: Pin<&mut InspectReader<R, F>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<S> AsyncRead for SinkWriter<S>
where + S: AsyncRead,

§

fn poll_read( + self: Pin<&mut SinkWriter<S>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<S, B, E> AsyncRead for StreamReader<S, B>
where + S: Stream<Item = Result<B, E>>, + B: Buf, + E: Into<Error>,

§

fn poll_read( + self: Pin<&mut StreamReader<S, B>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<T> AsyncRead for &mut T
where + T: AsyncRead + Unpin + ?Sized,

§

fn poll_read( + self: Pin<&mut &mut T>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<T> AsyncRead for Box<T>
where + T: AsyncRead + Unpin + ?Sized,

§

fn poll_read( + self: Pin<&mut Box<T>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<T> AsyncRead for Cursor<T>
where + T: AsRef<[u8]> + Unpin,

§

fn poll_read( + self: Pin<&mut Cursor<T>>, + _cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

§

impl<W, F> AsyncRead for InspectWriter<W, F>
where + W: AsyncRead,

§

fn poll_read( + self: Pin<&mut InspectWriter<W, F>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Implementors§

§

impl AsyncRead for OwnedReadHalf

§

impl AsyncRead for OwnedReadHalf

§

impl AsyncRead for ReadHalf<'_>

§

impl AsyncRead for ReadHalf<'_>

§

impl AsyncRead for Receiver

§

impl AsyncRead for TcpStream

§

impl AsyncRead for UnixStream

\ No newline at end of file diff --git a/actix_codec/trait.AsyncWrite.html b/actix_codec/trait.AsyncWrite.html new file mode 100644 index 00000000..47f391d5 --- /dev/null +++ b/actix_codec/trait.AsyncWrite.html @@ -0,0 +1,334 @@ +AsyncWrite in actix_codec - Rust
actix_codec

Trait AsyncWrite

pub trait AsyncWrite {
+    // Required methods
+    fn poll_write(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<Result<usize, Error>>;
+    fn poll_flush(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+    ) -> Poll<Result<(), Error>>;
+    fn poll_shutdown(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+    ) -> Poll<Result<(), Error>>;
+
+    // Provided methods
+    fn poll_write_vectored(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        bufs: &[IoSlice<'_>],
+    ) -> Poll<Result<usize, Error>> { ... }
+    fn is_write_vectored(&self) -> bool { ... }
+}
Expand description

Writes bytes asynchronously.

+

The trait inherits from std::io::Write and indicates that an I/O object is +nonblocking. All non-blocking I/O objects must return an error when +bytes cannot be written instead of blocking the current thread.

+

Specifically, this means that the poll_write function will return one of +the following:

+
    +
  • +

    Poll::Ready(Ok(n)) means that n bytes of data was immediately +written.

    +
  • +
  • +

    Poll::Pending means that no data was written from the buffer +provided. The I/O object is not currently writable but may become writable +in the future. Most importantly, the current future’s task is scheduled +to get unparked when the object is writable. This means that like +Future::poll you’ll receive a notification when the I/O object is +writable again.

    +
  • +
  • +

    Poll::Ready(Err(e)) for other errors are standard I/O errors coming from the +underlying object.

    +
  • +
+

This trait importantly means that the write method only works in +the context of a future’s task. The object may panic if used outside of a task.

+

Note that this trait also represents that the Write::flush method +works very similarly to the write method, notably that Ok(()) means that the +writer has successfully been flushed, a “would block” error means that the +current task is ready to receive a notification when flushing can make more +progress, and otherwise normal errors can happen as well.

+

Utilities for working with AsyncWrite values are provided by +AsyncWriteExt.

+

Required Methods§

fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Attempt to write bytes from buf into the object.

+

On success, returns Poll::Ready(Ok(num_bytes_written)). If successful, +then it must be guaranteed that n <= buf.len(). A return value of 0 +typically means that the underlying object is no longer able to accept +bytes and will likely not be able to in the future as well, or that the +buffer provided is empty.

+

If the object is not ready for writing, the method returns +Poll::Pending and arranges for the current task (via +cx.waker()) to receive a notification when the object becomes +writable or is closed.

+

fn poll_flush( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination.

+

On success, returns Poll::Ready(Ok(())).

+

If flushing cannot immediately complete, this method returns +Poll::Pending and arranges for the current task (via +cx.waker()) to receive a notification when the object can make +progress towards flushing.

+

fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down.

+

This method is intended to be used for asynchronous shutdown of I/O +connections. For example this is suitable for implementing shutdown of a +TLS connection or calling TcpStream::shutdown on a proxied connection. +Protocols sometimes need to flush out final pieces of data or otherwise +perform a graceful shutdown handshake, reading/writing more data as +appropriate. This method is the hook for such protocols to implement the +graceful shutdown logic.

+

This shutdown method is required by implementers of the +AsyncWrite trait. Wrappers typically just want to proxy this call +through to the wrapped type, and base types will typically implement +shutdown logic here or just return Ok(().into()). Note that if you’re +wrapping an underlying AsyncWrite a call to shutdown implies that +transitively the entire stream has been shut down. After your wrapper’s +shutdown logic has been executed you should shut down the underlying +stream.

+

Invocation of a shutdown implies an invocation of flush. Once this +method returns Ready it implies that a flush successfully happened +before the shutdown happened. That is, callers don’t need to call +flush before calling shutdown. They can rely that by calling +shutdown any pending buffered data will be written out.

+
§Return value
+

This function returns a Poll<io::Result<()>> classified as such:

+
    +
  • +

    Poll::Ready(Ok(())) - indicates that the connection was +successfully shut down and is now safe to deallocate/drop/close +resources associated with it. This method means that the current task +will no longer receive any notifications due to this method and the +I/O object itself is likely no longer usable.

    +
  • +
  • +

    Poll::Pending - indicates that shutdown is initiated but could +not complete just yet. This may mean that more I/O needs to happen to +continue this shutdown operation. The current task is scheduled to +receive a notification when it’s otherwise ready to continue the +shutdown operation. When woken up this method should be called again.

    +
  • +
  • +

    Poll::Ready(Err(e)) - indicates a fatal error has happened with shutdown, +indicating that the shutdown operation did not complete successfully. +This typically means that the I/O object is no longer usable.

    +
  • +
+
§Errors
+

This function can return normal I/O errors through Err, described +above. Additionally this method may also render the underlying +Write::write method no longer usable (e.g. will return errors in the +future). It’s recommended that once shutdown is called the +write method is no longer called.

+
§Panics
+

This function will panic if not called within the context of a future’s +task.

+

Provided Methods§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers.

+

Data is copied from each buffer in order, with the final buffer +read from possibly being only partially consumed. This method must +behave as a call to write with the buffers concatenated would.

+

The default implementation calls poll_write with either the first nonempty +buffer provided, or an empty one if none exists.

+

On success, returns Poll::Ready(Ok(num_bytes_written)).

+

If the object is not ready for writing, the method returns +Poll::Pending and arranges for the current task (via +cx.waker()) to receive a notification when the object becomes +writable or is closed.

+
§Note
+

This should be implemented as a single “atomic” write action. If any +data has been partially written, it is wrong to return an error or +pending.

+

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation.

+

If a writer does not override the default poll_write_vectored +implementation, code using it may want to avoid the method all together +and coalesce writes into a single buffer for higher performance.

+

The default implementation returns false.

+

Implementations on Foreign Types§

§

impl AsyncWrite for Vec<u8>

§

fn poll_write( + self: Pin<&mut Vec<u8>>, + _cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut Vec<u8>>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut Vec<u8>>, + _cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Vec<u8>>, + _cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl AsyncWrite for Cursor<&mut Vec<u8>>

§

fn poll_write( + self: Pin<&mut Cursor<&mut Vec<u8>>>, + _: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut Cursor<&mut Vec<u8>>>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut Cursor<&mut Vec<u8>>>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Cursor<&mut Vec<u8>>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl AsyncWrite for Cursor<&mut [u8]>

§

fn poll_write( + self: Pin<&mut Cursor<&mut [u8]>>, + _: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut Cursor<&mut [u8]>>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut Cursor<&mut [u8]>>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Cursor<&mut [u8]>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl AsyncWrite for Cursor<Box<[u8]>>

§

fn poll_write( + self: Pin<&mut Cursor<Box<[u8]>>>, + _: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut Cursor<Box<[u8]>>>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut Cursor<Box<[u8]>>>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Cursor<Box<[u8]>>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl AsyncWrite for Cursor<Vec<u8>>

§

fn poll_write( + self: Pin<&mut Cursor<Vec<u8>>>, + _: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut Cursor<Vec<u8>>>, + _: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut Cursor<Vec<u8>>>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Cursor<Vec<u8>>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl<L, R> AsyncWrite for Either<L, R>
where + L: AsyncWrite, + R: AsyncWrite,

§

fn poll_write( + self: Pin<&mut Either<L, R>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_flush( + self: Pin<&mut Either<L, R>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Either<L, R>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl<P> AsyncWrite for Pin<P>
where + P: DerefMut + Unpin, + <P as Deref>::Target: AsyncWrite,

§

fn poll_write( + self: Pin<&mut Pin<P>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut Pin<P>>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut Pin<P>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Pin<P>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl<R, F> AsyncWrite for InspectReader<R, F>
where + R: AsyncWrite,

§

fn poll_write( + self: Pin<&mut InspectReader<R, F>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_flush( + self: Pin<&mut InspectReader<R, F>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut InspectReader<R, F>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_write_vectored( + self: Pin<&mut InspectReader<R, F>>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

impl<S, E> AsyncWrite for SinkWriter<S>
where + S: for<'a> Sink<&'a [u8], Error = E>, + E: Into<Error>,

§

fn poll_write( + self: Pin<&mut SinkWriter<S>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_flush( + self: Pin<&mut SinkWriter<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut SinkWriter<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl<T> AsyncWrite for &mut T
where + T: AsyncWrite + Unpin + ?Sized,

§

fn poll_write( + self: Pin<&mut &mut T>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut &mut T>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut &mut T>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut &mut T>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl<T> AsyncWrite for Box<T>
where + T: AsyncWrite + Unpin + ?Sized,

§

fn poll_write( + self: Pin<&mut Box<T>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_write_vectored( + self: Pin<&mut Box<T>>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

§

fn poll_flush( + self: Pin<&mut Box<T>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut Box<T>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

impl<W, F> AsyncWrite for InspectWriter<W, F>
where + W: AsyncWrite, + F: FnMut(&[u8]),

§

fn poll_write( + self: Pin<&mut InspectWriter<W, F>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

§

fn poll_flush( + self: Pin<&mut InspectWriter<W, F>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_shutdown( + self: Pin<&mut InspectWriter<W, F>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

§

fn poll_write_vectored( + self: Pin<&mut InspectWriter<W, F>>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

§

fn is_write_vectored(&self) -> bool

Implementors§

§

impl AsyncWrite for OwnedWriteHalf

§

impl AsyncWrite for OwnedWriteHalf

§

impl AsyncWrite for Sender

§

impl AsyncWrite for TcpStream

§

impl AsyncWrite for UnixStream

§

impl AsyncWrite for WriteHalf<'_>

§

impl AsyncWrite for WriteHalf<'_>

\ No newline at end of file diff --git a/actix_codec/trait.Decoder.html b/actix_codec/trait.Decoder.html new file mode 100644 index 00000000..c6c636f2 --- /dev/null +++ b/actix_codec/trait.Decoder.html @@ -0,0 +1,130 @@ +Decoder in actix_codec - Rust
actix_codec

Trait Decoder

pub trait Decoder {
+    type Item;
+    type Error: From<Error>;
+
+    // Required method
+    fn decode(
+        &mut self,
+        src: &mut BytesMut,
+    ) -> Result<Option<Self::Item>, Self::Error>;
+
+    // Provided methods
+    fn decode_eof(
+        &mut self,
+        buf: &mut BytesMut,
+    ) -> Result<Option<Self::Item>, Self::Error> { ... }
+    fn framed<T>(self, io: T) -> Framed<T, Self>
+       where T: AsyncRead + AsyncWrite,
+             Self: Sized { ... }
+}
Expand description

Decoding of frames via buffers.

+

This trait is used when constructing an instance of Framed or +FramedRead. An implementation of Decoder takes a byte stream that has +already been buffered in src and decodes the data into a stream of +Self::Item frames.

+

Implementations are able to track state on self, which enables +implementing stateful streaming parsers. In many cases, though, this type +will simply be a unit struct (e.g. struct HttpDecoder).

+

For some underlying data-sources, namely files and FIFOs, +it’s possible to temporarily read 0 bytes by reaching EOF.

+

In these cases decode_eof will be called until it signals +fulfillment of all closing frames by returning Ok(None). +After that, repeated attempts to read from the Framed or FramedRead +will not invoke decode or decode_eof again, until data can be read +during a retry.

+

It is up to the Decoder to keep track of a restart after an EOF, +and to decide how to handle such an event by, for example, +allowing frames to cross EOF boundaries, re-emitting opening frames, or +resetting the entire internal state.

+

Required Associated Types§

type Item

The type of decoded frames.

+

type Error: From<Error>

The type of unrecoverable frame decoding errors.

+

If an individual message is ill-formed but can be ignored without +interfering with the processing of future messages, it may be more +useful to report the failure as an Item.

+

From<io::Error> is required in the interest of making Error suitable +for returning directly from a FramedRead, and to enable the default +implementation of decode_eof to yield an io::Error when the decoder +fails to consume all available data.

+

Note that implementors of this trait can simply indicate type Error = io::Error to use I/O errors as this type.

+

Required Methods§

fn decode( + &mut self, + src: &mut BytesMut, +) -> Result<Option<Self::Item>, Self::Error>

Attempts to decode a frame from the provided buffer of bytes.

+

This method is called by FramedRead whenever bytes are ready to be +parsed. The provided buffer of bytes is what’s been read so far, and +this instance of Decode can determine whether an entire frame is in +the buffer and is ready to be returned.

+

If an entire frame is available, then this instance will remove those +bytes from the buffer provided and return them as a decoded +frame. Note that removing bytes from the provided buffer doesn’t always +necessarily copy the bytes, so this should be an efficient operation in +most circumstances.

+

If the bytes look valid, but a frame isn’t fully available yet, then +Ok(None) is returned. This indicates to the Framed instance that +it needs to read some more bytes before calling this method again.

+

Note that the bytes provided may be empty. If a previous call to +decode consumed all the bytes in the buffer then decode will be +called again until it returns Ok(None), indicating that more bytes need to +be read.

+

Finally, if the bytes in the buffer are malformed then an error is +returned indicating why. This informs Framed that the stream is now +corrupt and should be terminated.

+
§Buffer management
+

Before returning from the function, implementations should ensure that +the buffer has appropriate capacity in anticipation of future calls to +decode. Failing to do so leads to inefficiency.

+

For example, if frames have a fixed length, or if the length of the +current frame is known from a header, a possible buffer management +strategy is:

+ +
impl Decoder for MyCodec {
+    // ...
+
+    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
+        // ...
+
+        // Reserve enough to complete decoding of the current frame.
+        let current_frame_len: usize = 1000; // Example.
+        // And to start decoding the next frame.
+        let next_frame_header_len: usize = 10; // Example.
+        src.reserve(current_frame_len + next_frame_header_len);
+
+        return Ok(None);
+    }
+}
+

An optimal buffer management strategy minimizes reallocations and +over-allocations.

+

Provided Methods§

fn decode_eof( + &mut self, + buf: &mut BytesMut, +) -> Result<Option<Self::Item>, Self::Error>

A default method available to be called when there are no more bytes +available to be read from the underlying I/O.

+

This method defaults to calling decode and returns an error if +Ok(None) is returned while there is unconsumed data in buf. +Typically this doesn’t need to be implemented unless the framing +protocol differs near the end of the stream, or if you need to construct +frames across eof boundaries on sources that can be resumed.

+

Note that the buf argument may be empty. If a previous call to +decode_eof consumed all the bytes in the buffer, decode_eof will be +called again until it returns None, indicating that there are no more +frames to yield. This behavior enables returning finalization frames +that may not be based on inbound data.

+

Once None has been returned, decode_eof won’t be called again until +an attempt to resume the stream has been made, where the underlying stream +actually returned more data.

+

fn framed<T>(self, io: T) -> Framed<T, Self>
where + T: AsyncRead + AsyncWrite, + Self: Sized,

Provides a Stream and Sink interface for reading and writing to this +Io object, using Decode and Encode to read and write the raw data.

+

Raw I/O objects work with byte sequences, but higher-level code usually +wants to batch these into meaningful chunks, called “frames”. This +method layers framing on top of an I/O object, by using the Codec +traits to handle encoding and decoding of messages frames. Note that +the incoming and outgoing frame types may be distinct.

+

This function returns a single object that is both Stream and +Sink; grouping this into a single object is often useful for layering +things like gzip or TLS, which require both read and write access to the +underlying object.

+

If you want to work more directly with the streams and sink, consider +calling split on the Framed returned by this method, which will +break them into separate objects, allowing them to interact more easily.

+

Implementors§

source§

impl Decoder for actix_codec::BytesCodec

source§

type Item = BytesMut

source§

type Error = Error

source§

impl Decoder for actix_codec::LinesCodec

§

impl Decoder for AnyDelimiterCodec

§

type Item = Bytes

§

type Error = AnyDelimiterCodecError

§

impl Decoder for BytesCodec

§

type Item = BytesMut

§

type Error = Error

§

impl Decoder for LengthDelimitedCodec

§

type Item = BytesMut

§

type Error = Error

§

impl Decoder for LinesCodec

§

type Item = String

§

type Error = LinesCodecError

\ No newline at end of file diff --git a/actix_codec/trait.Encoder.html b/actix_codec/trait.Encoder.html new file mode 100644 index 00000000..febe4c9b --- /dev/null +++ b/actix_codec/trait.Encoder.html @@ -0,0 +1,21 @@ +Encoder in actix_codec - Rust
actix_codec

Trait Encoder

pub trait Encoder<Item> {
+    type Error: From<Error>;
+
+    // Required method
+    fn encode(
+        &mut self,
+        item: Item,
+        dst: &mut BytesMut,
+    ) -> Result<(), Self::Error>;
+}
Expand description

Trait of helper objects to write out messages as bytes, for use with +FramedWrite.

+

Required Associated Types§

type Error: From<Error>

The type of encoding errors.

+

FramedWrite requires Encoders errors to implement From<io::Error> +in the interest of letting it return Errors directly.

+

Required Methods§

fn encode(&mut self, item: Item, dst: &mut BytesMut) -> Result<(), Self::Error>

Encodes a frame into the buffer provided.

+

This method will encode item into the byte buffer provided by dst. +The dst provided is an internal buffer of the FramedWrite instance and +will be written out when possible.

+

Implementors§

source§

impl Encoder<Bytes> for actix_codec::BytesCodec

§

impl Encoder<Bytes> for BytesCodec

§

type Error = Error

§

impl Encoder<Bytes> for LengthDelimitedCodec

§

type Error = Error

§

impl Encoder<BytesMut> for BytesCodec

§

type Error = Error

§

impl<T> Encoder<T> for AnyDelimiterCodec
where + T: AsRef<str>,

§

type Error = AnyDelimiterCodecError

§

impl<T> Encoder<T> for LinesCodec
where + T: AsRef<str>,

§

type Error = LinesCodecError

source§

impl<T: AsRef<str>> Encoder<T> for actix_codec::LinesCodec

\ No newline at end of file diff --git a/actix_macros/all.html b/actix_macros/all.html new file mode 100644 index 00000000..04284974 --- /dev/null +++ b/actix_macros/all.html @@ -0,0 +1 @@ +List of all items in this crate

List of all items

Attribute Macros

\ No newline at end of file diff --git a/actix_macros/attr.main.html b/actix_macros/attr.main.html new file mode 100644 index 00000000..43fcf3ad --- /dev/null +++ b/actix_macros/attr.main.html @@ -0,0 +1,7 @@ +main in actix_macros - Rust
actix_macros

Attribute Macro main

source
#[main]
Expand description

Marks async entry-point function to be executed by Actix system.

+

§Examples

+
#[actix_rt::main]
+async fn main() {
+    println!("Hello world");
+}
+
\ No newline at end of file diff --git a/actix_macros/attr.test.html b/actix_macros/attr.test.html new file mode 100644 index 00000000..52558261 --- /dev/null +++ b/actix_macros/attr.test.html @@ -0,0 +1,7 @@ +test in actix_macros - Rust
actix_macros

Attribute Macro test

source
#[test]
Expand description

Marks async test function to be executed in an Actix system.

+

§Examples

+
#[actix_rt::test]
+async fn my_test() {
+    assert!(true);
+}
+
\ No newline at end of file diff --git a/actix_macros/index.html b/actix_macros/index.html new file mode 100644 index 00000000..d7b3ece2 --- /dev/null +++ b/actix_macros/index.html @@ -0,0 +1,7 @@ +actix_macros - Rust

Crate actix_macros

source
Expand description

Macros for Actix system and runtime.

+

The actix-rt crate must be available for macro output to compile.

+

§Entry-point

+

See docs for the #[main] macro.

+

§Tests

+

See docs for the #[test] macro.

+

Attribute Macros§

  • Marks async entry-point function to be executed by Actix system.
  • Marks async test function to be executed in an Actix system.
\ No newline at end of file diff --git a/actix_macros/sidebar-items.js b/actix_macros/sidebar-items.js new file mode 100644 index 00000000..f2a173d7 --- /dev/null +++ b/actix_macros/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"attr":["main","test"]}; \ No newline at end of file diff --git a/actix_rt/all.html b/actix_rt/all.html new file mode 100644 index 00000000..024d5c5d --- /dev/null +++ b/actix_rt/all.html @@ -0,0 +1 @@ +List of all items in this crate
\ No newline at end of file diff --git a/actix_rt/arbiter/struct.Arbiter.html b/actix_rt/arbiter/struct.Arbiter.html new file mode 100644 index 00000000..fb91428d --- /dev/null +++ b/actix_rt/arbiter/struct.Arbiter.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_rt/struct.Arbiter.html...

+ + + \ No newline at end of file diff --git a/actix_rt/arbiter/struct.ArbiterHandle.html b/actix_rt/arbiter/struct.ArbiterHandle.html new file mode 100644 index 00000000..6d9f0775 --- /dev/null +++ b/actix_rt/arbiter/struct.ArbiterHandle.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_rt/struct.ArbiterHandle.html...

+ + + \ No newline at end of file diff --git a/actix_rt/attr.main.html b/actix_rt/attr.main.html new file mode 100644 index 00000000..d8f84e6d --- /dev/null +++ b/actix_rt/attr.main.html @@ -0,0 +1,7 @@ +main in actix_rt - Rust
actix_rt

Attribute Macro main

#[main]
Expand description

Marks async entry-point function to be executed by Actix system.

+

§Examples

+
#[actix_rt::main]
+async fn main() {
+    println!("Hello world");
+}
+
\ No newline at end of file diff --git a/actix_rt/attr.test.html b/actix_rt/attr.test.html new file mode 100644 index 00000000..6269cb55 --- /dev/null +++ b/actix_rt/attr.test.html @@ -0,0 +1,7 @@ +test in actix_rt - Rust
actix_rt

Attribute Macro test

#[test]
Expand description

Marks async test function to be executed in an Actix system.

+

§Examples

+
#[actix_rt::test]
+async fn my_test() {
+    assert!(true);
+}
+
\ No newline at end of file diff --git a/actix_rt/fn.spawn.html b/actix_rt/fn.spawn.html new file mode 100644 index 00000000..8589d87e --- /dev/null +++ b/actix_rt/fn.spawn.html @@ -0,0 +1,24 @@ +spawn in actix_rt - Rust
actix_rt

Function spawn

source
pub fn spawn<Fut>(f: Fut) -> JoinHandle<Fut::Output> 
where + Fut: Future + 'static, + Fut::Output: 'static,
Expand description

Spawns a future on the current thread as a new task.

+

If not immediately awaited, the task can be cancelled using JoinHandle::abort.

+

The provided future is spawned as a new task; therefore, panics are caught.

+

§Panics

+

Panics if Actix system is not running.

+

§Examples

+
// task resolves successfully
+assert_eq!(actix_rt::spawn(async { 1 }).await.unwrap(), 1);
+
+// task panics
+assert!(actix_rt::spawn(async {
+    panic!("panic is caught at task boundary");
+})
+.await
+.unwrap_err()
+.is_panic());
+
+// task is cancelled before completion
+let handle = actix_rt::spawn(actix_rt::time::sleep(Duration::from_secs(100)));
+handle.abort();
+assert!(handle.await.unwrap_err().is_cancelled());
+
\ No newline at end of file diff --git a/actix_rt/index.html b/actix_rt/index.html new file mode 100644 index 00000000..0e1bae19 --- /dev/null +++ b/actix_rt/index.html @@ -0,0 +1,35 @@ +actix_rt - Rust

Crate actix_rt

source
Expand description

Tokio-based single-threaded async runtime for the Actix ecosystem.

+

In most parts of the the Actix ecosystem, it has been chosen to use !Send futures. For this +reason, a single-threaded runtime is appropriate since it is guaranteed that futures will not +be moved between threads. This can result in small performance improvements over cases where +atomics would otherwise be needed.

+

To achieve similar performance to multi-threaded, work-stealing runtimes, applications +using actix-rt will create multiple, mostly disconnected, single-threaded runtimes. +This approach has good performance characteristics for workloads where the majority of tasks +have similar runtime expense.

+

The disadvantage is that idle threads will not steal work from very busy, stuck or otherwise +backlogged threads. Tasks that are disproportionately expensive should be offloaded to the +blocking task thread-pool using task::spawn_blocking.

+

§Examples

+
use std::sync::mpsc;
+use actix_rt::{Arbiter, System};
+
+let _ = System::new();
+
+let (tx, rx) = mpsc::channel::<u32>();
+
+let arbiter = Arbiter::new();
+arbiter.spawn_fn(move || tx.send(42).unwrap());
+
+let num = rx.recv().unwrap();
+assert_eq!(num, 42);
+
+arbiter.stop();
+arbiter.join().unwrap();
+

§io-uring Support

+

There is experimental support for using io-uring with this crate by enabling the +io-uring feature. For now, it is semver exempt.

+

Note that there are currently some unimplemented parts of using actix-rt with io-uring. +In particular, when running a System, only System::block_on is supported.

+

Modules§

  • TCP/UDP/Unix bindings (mostly Tokio re-exports).
  • Asynchronous signal handling (Tokio re-exports).
  • Task management (Tokio re-exports).
  • Utilities for tracking time (Tokio re-exports).

Macros§

  • Pins a value on the stack.

Structs§

  • An Arbiter represents a thread that provides an asynchronous execution environment for futures +and functions.
  • A handle for sending spawn and stop messages to an Arbiter.
  • A Tokio-based runtime proxy.
  • A manager for a per-thread distributed async runtime.
  • Runner that keeps a System’s event loop alive until stop message is received.

Functions§

  • Spawns a future on the current thread as a new task.

Attribute Macros§

  • Marks async entry-point function to be executed by Actix system.
  • Marks async test function to be executed in an Actix system.
\ No newline at end of file diff --git a/actix_rt/macro.pin!.html b/actix_rt/macro.pin!.html new file mode 100644 index 00000000..22b3e842 --- /dev/null +++ b/actix_rt/macro.pin!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.pin.html...

+ + + \ No newline at end of file diff --git a/actix_rt/macro.pin.html b/actix_rt/macro.pin.html new file mode 100644 index 00000000..eac19464 --- /dev/null +++ b/actix_rt/macro.pin.html @@ -0,0 +1,104 @@ +pin in actix_rt - Rust
actix_rt

Macro pin

macro_rules! pin {
+    ($($x:ident),*) => { ... };
+    ($(
+            let $x:ident = $init:expr;
+    )*) => { ... };
+}
Expand description

Pins a value on the stack.

+

Calls to async fn return anonymous Future values that are !Unpin. +These values must be pinned before they can be polled. Calling .await will +handle this, but consumes the future. If it is required to call .await on +a &mut _ reference, the caller is responsible for pinning the future.

+

Pinning may be done by allocating with Box::pin or by using the stack +with the pin! macro.

+

The following will fail to compile:

+ +
async fn my_async_fn() {
+    // async logic here
+}
+
+#[tokio::main]
+async fn main() {
+    let mut future = my_async_fn();
+    (&mut future).await;
+}
+

To make this work requires pinning:

+ +
use tokio::pin;
+
+async fn my_async_fn() {
+    // async logic here
+}
+
+#[tokio::main]
+async fn main() {
+    let future = my_async_fn();
+    pin!(future);
+
+    (&mut future).await;
+}
+

Pinning is useful when using select! and stream operators that require T: Stream + Unpin.

+

§Usage

+

The pin! macro takes identifiers as arguments. It does not work +with expressions.

+

The following does not compile as an expression is passed to pin!.

+ +
async fn my_async_fn() {
+    // async logic here
+}
+
+#[tokio::main]
+async fn main() {
+    let mut future = pin!(my_async_fn());
+    (&mut future).await;
+}
+

§Examples

+

Using with select:

+ +
use tokio::{pin, select};
+use tokio_stream::{self as stream, StreamExt};
+
+async fn my_async_fn() {
+    // async logic here
+}
+
+#[tokio::main]
+async fn main() {
+    let mut stream = stream::iter(vec![1, 2, 3, 4]);
+
+    let future = my_async_fn();
+    pin!(future);
+
+    loop {
+        select! {
+            _ = &mut future => {
+                // Stop looping `future` will be polled after completion
+                break;
+            }
+            Some(val) = stream.next() => {
+                println!("got value = {}", val);
+            }
+        }
+    }
+}
+

Because assigning to a variable followed by pinning is common, there is also +a variant of the macro that supports doing both in one go.

+ +
use tokio::{pin, select};
+
+async fn my_async_fn() {
+    // async logic here
+}
+
+#[tokio::main]
+async fn main() {
+    pin! {
+        let future1 = my_async_fn();
+        let future2 = my_async_fn();
+    }
+
+    select! {
+        _ = &mut future1 => {}
+        _ = &mut future2 => {}
+    }
+}
+
\ No newline at end of file diff --git a/actix_rt/net/index.html b/actix_rt/net/index.html new file mode 100644 index 00000000..909c9d82 --- /dev/null +++ b/actix_rt/net/index.html @@ -0,0 +1,3 @@ +actix_rt::net - Rust
actix_rt

Module net

source
Expand description

TCP/UDP/Unix bindings (mostly Tokio re-exports).

+

Structs§

  • Describes the readiness state of an I/O resources.
  • A TCP socket server, listening for connections.
  • A TCP socket that has not yet been converted to a TcpStream or +TcpListener.
  • A TCP stream between a local and a remote socket.
  • A UDP socket.
  • An I/O object representing a Unix datagram socket.
  • A Unix socket which can accept connections from other Unix sockets.
  • A structure representing a connected Unix socket.
\ No newline at end of file diff --git a/actix_rt/net/sidebar-items.js b/actix_rt/net/sidebar-items.js new file mode 100644 index 00000000..2f29502d --- /dev/null +++ b/actix_rt/net/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["Ready","TcpListener","TcpSocket","TcpStream","UdpSocket","UnixDatagram","UnixListener","UnixStream"]}; \ No newline at end of file diff --git a/actix_rt/net/struct.Ready.html b/actix_rt/net/struct.Ready.html new file mode 100644 index 00000000..94a17c7b --- /dev/null +++ b/actix_rt/net/struct.Ready.html @@ -0,0 +1,80 @@ +Ready in actix_rt::net - Rust
actix_rt::net

Struct Ready

pub struct Ready(/* private fields */);
Expand description

Describes the readiness state of an I/O resources.

+

Ready tracks which operation an I/O resource is ready to perform.

+

Implementations§

§

impl Ready

pub const EMPTY: Ready = _

Returns the empty Ready set.

+

pub const READABLE: Ready = _

Returns a Ready representing readable readiness.

+

pub const WRITABLE: Ready = _

Returns a Ready representing writable readiness.

+

pub const READ_CLOSED: Ready = _

Returns a Ready representing read closed readiness.

+

pub const WRITE_CLOSED: Ready = _

Returns a Ready representing write closed readiness.

+

pub const PRIORITY: Ready = _

Returns a Ready representing priority readiness.

+

pub const ERROR: Ready = _

Returns a Ready representing error readiness.

+

pub const ALL: Ready = _

Returns a Ready representing readiness for all operations.

+

pub fn is_empty(self) -> bool

Returns true if Ready is the empty set.

+
§Examples
+
use tokio::io::Ready;
+
+assert!(Ready::EMPTY.is_empty());
+assert!(!Ready::READABLE.is_empty());
+

pub fn is_readable(self) -> bool

Returns true if the value includes readable.

+
§Examples
+
use tokio::io::Ready;
+
+assert!(!Ready::EMPTY.is_readable());
+assert!(Ready::READABLE.is_readable());
+assert!(Ready::READ_CLOSED.is_readable());
+assert!(!Ready::WRITABLE.is_readable());
+

pub fn is_writable(self) -> bool

Returns true if the value includes writable readiness.

+
§Examples
+
use tokio::io::Ready;
+
+assert!(!Ready::EMPTY.is_writable());
+assert!(!Ready::READABLE.is_writable());
+assert!(Ready::WRITABLE.is_writable());
+assert!(Ready::WRITE_CLOSED.is_writable());
+

pub fn is_read_closed(self) -> bool

Returns true if the value includes read-closed readiness.

+
§Examples
+
use tokio::io::Ready;
+
+assert!(!Ready::EMPTY.is_read_closed());
+assert!(!Ready::READABLE.is_read_closed());
+assert!(Ready::READ_CLOSED.is_read_closed());
+

pub fn is_write_closed(self) -> bool

Returns true if the value includes write-closed readiness.

+
§Examples
+
use tokio::io::Ready;
+
+assert!(!Ready::EMPTY.is_write_closed());
+assert!(!Ready::WRITABLE.is_write_closed());
+assert!(Ready::WRITE_CLOSED.is_write_closed());
+

pub fn is_priority(self) -> bool

Returns true if the value includes priority readiness.

+
§Examples
+
use tokio::io::Ready;
+
+assert!(!Ready::EMPTY.is_priority());
+assert!(!Ready::WRITABLE.is_priority());
+assert!(Ready::PRIORITY.is_priority());
+

pub fn is_error(self) -> bool

Returns true if the value includes error readiness.

+
§Examples
+
use tokio::io::Ready;
+
+assert!(!Ready::EMPTY.is_error());
+assert!(!Ready::WRITABLE.is_error());
+assert!(Ready::ERROR.is_error());
+

Trait Implementations§

§

impl BitAnd for Ready

§

type Output = Ready

The resulting type after applying the & operator.
§

fn bitand(self, other: Ready) -> Ready

Performs the & operation. Read more
§

impl BitOr for Ready

§

type Output = Ready

The resulting type after applying the | operator.
§

fn bitor(self, other: Ready) -> Ready

Performs the | operation. Read more
§

impl BitOrAssign for Ready

§

fn bitor_assign(&mut self, other: Ready)

Performs the |= operation. Read more
§

impl Clone for Ready

§

fn clone(&self) -> Ready

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for Ready

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Ord for Ready

§

fn cmp(&self, other: &Ready) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized,

Restrict a value to a certain interval. Read more
§

impl PartialEq for Ready

§

fn eq(&self, other: &Ready) -> bool

Tests for self and other values to be equal, and is used by ==.
1.6.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
§

impl PartialOrd for Ready

§

fn partial_cmp(&self, other: &Ready) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.6.0 · source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.6.0 · source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the +<= operator. Read more
1.6.0 · source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > +operator. Read more
1.6.0 · source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by +the >= operator. Read more
§

impl Sub for Ready

§

type Output = Ready

The resulting type after applying the - operator.
§

fn sub(self, other: Ready) -> Ready

Performs the - operation. Read more
§

impl Copy for Ready

§

impl Eq for Ready

§

impl StructuralPartialEq for Ready

Auto Trait Implementations§

§

impl Freeze for Ready

§

impl RefUnwindSafe for Ready

§

impl Send for Ready

§

impl Sync for Ready

§

impl Unpin for Ready

§

impl UnwindSafe for Ready

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/net/struct.TcpListener.html b/actix_rt/net/struct.TcpListener.html new file mode 100644 index 00000000..02748148 --- /dev/null +++ b/actix_rt/net/struct.TcpListener.html @@ -0,0 +1,198 @@ +TcpListener in actix_rt::net - Rust
actix_rt::net

Struct TcpListener

pub struct TcpListener { /* private fields */ }
Expand description

A TCP socket server, listening for connections.

+

You can accept a new connection by using the accept +method.

+

A TcpListener can be turned into a Stream with TcpListenerStream.

+

§Errors

+

Note that accepting a connection can lead to various errors and not all +of them are necessarily fatal ‒ for example having too many open file +descriptors or the other side closing the connection while it waits in +an accept queue. These would terminate the stream if not handled in any +way.

+

§Examples

+

Using accept:

+ +
use tokio::net::TcpListener;
+
+use std::io;
+
+async fn process_socket<T>(socket: T) {
+    // do work with socket here
+}
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let listener = TcpListener::bind("127.0.0.1:8080").await?;
+
+    loop {
+        let (socket, _) = listener.accept().await?;
+        process_socket(socket).await;
+    }
+}
+

Implementations§

§

impl TcpListener

pub async fn bind<A>(addr: A) -> Result<TcpListener, Error>
where + A: ToSocketAddrs,

Creates a new TcpListener, which will be bound to the specified address.

+

The returned listener is ready for accepting connections.

+

Binding with a port number of 0 will request that the OS assigns a port +to this listener. The port allocated can be queried via the local_addr +method.

+

The address type can be any implementor of the ToSocketAddrs trait. +If addr yields multiple addresses, bind will be attempted with each of +the addresses until one succeeds and returns the listener. If none of +the addresses succeed in creating a listener, the error returned from +the last attempt (the last address) is returned.

+

This function sets the SO_REUSEADDR option on the socket.

+

To configure the socket before binding, you can use the TcpSocket +type.

+
§Examples
+
use tokio::net::TcpListener;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let listener = TcpListener::bind("127.0.0.1:2345").await?;
+
+    // use the listener
+
+    Ok(())
+}
+

pub async fn accept(&self) -> Result<(TcpStream, SocketAddr), Error>

Accepts a new incoming connection from this listener.

+

This function will yield once a new TCP connection is established. When +established, the corresponding TcpStream and the remote peer’s +address will be returned.

+
§Cancel safety
+

This method is cancel safe. If the method is used as the event in a +tokio::select! statement and some other branch +completes first, then it is guaranteed that no new connections were +accepted by this method.

+
§Examples
+
use tokio::net::TcpListener;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let listener = TcpListener::bind("127.0.0.1:8080").await?;
+
+    match listener.accept().await {
+        Ok((_socket, addr)) => println!("new client: {:?}", addr),
+        Err(e) => println!("couldn't get client: {:?}", e),
+    }
+
+    Ok(())
+}
+

pub fn poll_accept( + &self, + cx: &mut Context<'_>, +) -> Poll<Result<(TcpStream, SocketAddr), Error>>

Polls to accept a new incoming connection to this listener.

+

If there is no connection to accept, Poll::Pending is returned and the +current task will be notified by a waker. Note that on multiple calls +to poll_accept, only the Waker from the Context passed to the most +recent call is scheduled to receive a wakeup.

+

pub fn from_std(listener: TcpListener) -> Result<TcpListener, Error>

Creates new TcpListener from a std::net::TcpListener.

+

This function is intended to be used to wrap a TCP listener from the +standard library in the Tokio equivalent.

+

This API is typically paired with the socket2 crate and the Socket +type to build up and customize a listener before it’s shipped off to the +backing event loop. This allows configuration of options like +SO_REUSEPORT, binding to multiple addresses, etc.

+
§Notes
+

The caller is responsible for ensuring that the listener is in +non-blocking mode. Otherwise all I/O operations on the listener +will block the thread, which will cause unexpected behavior. +Non-blocking mode can be set using set_nonblocking.

+
§Examples
+
use std::error::Error;
+use tokio::net::TcpListener;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let std_listener = std::net::TcpListener::bind("127.0.0.1:0")?;
+    std_listener.set_nonblocking(true)?;
+    let listener = TcpListener::from_std(std_listener)?;
+    Ok(())
+}
+
§Panics
+

This function panics if it is not called from within a runtime with +IO enabled.

+

The runtime is usually set implicitly when this function is called +from a future driven by a tokio runtime, otherwise runtime can be set +explicitly with Runtime::enter function.

+

pub fn into_std(self) -> Result<TcpListener, Error>

Turns a tokio::net::TcpListener into a std::net::TcpListener.

+

The returned std::net::TcpListener will have nonblocking mode set as +true. Use set_nonblocking to change the blocking mode if needed.

+
§Examples
+
use std::error::Error;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let tokio_listener = tokio::net::TcpListener::bind("127.0.0.1:0").await?;
+    let std_listener = tokio_listener.into_std()?;
+    std_listener.set_nonblocking(false)?;
+    Ok(())
+}
+

pub fn local_addr(&self) -> Result<SocketAddr, Error>

Returns the local address that this listener is bound to.

+

This can be useful, for example, when binding to port 0 to figure out +which port was actually bound.

+
§Examples
+
use tokio::net::TcpListener;
+
+use std::io;
+use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let listener = TcpListener::bind("127.0.0.1:8080").await?;
+
+    assert_eq!(listener.local_addr()?,
+               SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
+
+    Ok(())
+}
+

pub fn ttl(&self) -> Result<u32, Error>

Gets the value of the IP_TTL option for this socket.

+

For more information about this option, see set_ttl.

+
§Examples
+
use tokio::net::TcpListener;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+   let listener = TcpListener::bind("127.0.0.1:0").await?;
+
+   listener.set_ttl(100).expect("could not set TTL");
+   assert_eq!(listener.ttl()?, 100);
+
+   Ok(())
+}
+

pub fn set_ttl(&self, ttl: u32) -> Result<(), Error>

Sets the value for the IP_TTL option on this socket.

+

This value sets the time-to-live field that is used in every packet sent +from this socket.

+
§Examples
+
use tokio::net::TcpListener;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let listener = TcpListener::bind("127.0.0.1:0").await?;
+
+    listener.set_ttl(100).expect("could not set TTL");
+
+    Ok(())
+}
+

Trait Implementations§

§

impl AsFd for TcpListener

§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
§

impl AsRawFd for TcpListener

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl Debug for TcpListener

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl TryFrom<TcpListener> for TcpListener

§

fn try_from( + stream: TcpListener, +) -> Result<TcpListener, <TcpListener as TryFrom<TcpListener>>::Error>

Consumes stream, returning the tokio I/O object.

+

This is equivalent to +TcpListener::from_std(stream).

+
§

type Error = Error

The type returned in the event of a conversion error.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/net/struct.TcpSocket.html b/actix_rt/net/struct.TcpSocket.html new file mode 100644 index 00000000..cb62d924 --- /dev/null +++ b/actix_rt/net/struct.TcpSocket.html @@ -0,0 +1,394 @@ +TcpSocket in actix_rt::net - Rust
actix_rt::net

Struct TcpSocket

pub struct TcpSocket { /* private fields */ }
Expand description

A TCP socket that has not yet been converted to a TcpStream or +TcpListener.

+

TcpSocket wraps an operating system socket and enables the caller to +configure the socket before establishing a TCP connection or accepting +inbound connections. The caller is able to set socket option and explicitly +bind the socket with a socket address.

+

The underlying socket is closed when the TcpSocket value is dropped.

+

TcpSocket should only be used directly if the default configuration used +by TcpStream::connect and TcpListener::bind does not meet the required +use case.

+

Calling TcpStream::connect("127.0.0.1:8080") is equivalent to:

+ +
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    let stream = socket.connect(addr).await?;
+
+    Ok(())
+}
+

Calling TcpListener::bind("127.0.0.1:8080") is equivalent to:

+ +
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    // On platforms with Berkeley-derived sockets, this allows to quickly
+    // rebind a socket, without needing to wait for the OS to clean up the
+    // previous one.
+    //
+    // On Windows, this allows rebinding sockets which are actively in use,
+    // which allows “socket hijacking”, so we explicitly don't set it here.
+    // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
+    socket.set_reuseaddr(true)?;
+    socket.bind(addr)?;
+
+    let listener = socket.listen(1024)?;
+
+    Ok(())
+}
+

Setting socket options not explicitly provided by TcpSocket may be done by +accessing the RawFd/RawSocket using AsRawFd/AsRawSocket and +setting the option with a crate like socket2.

+

Implementations§

§

impl TcpSocket

pub fn new_v4() -> Result<TcpSocket, Error>

Creates a new socket configured for IPv4.

+

Calls socket(2) with AF_INET and SOCK_STREAM.

+
§Returns
+

On success, the newly created TcpSocket is returned. If an error is +encountered, it is returned instead.

+
§Examples
+

Create a new IPv4 socket and start listening.

+ +
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+    let socket = TcpSocket::new_v4()?;
+    socket.bind(addr)?;
+
+    let listener = socket.listen(128)?;
+    Ok(())
+}
+

pub fn new_v6() -> Result<TcpSocket, Error>

Creates a new socket configured for IPv6.

+

Calls socket(2) with AF_INET6 and SOCK_STREAM.

+
§Returns
+

On success, the newly created TcpSocket is returned. If an error is +encountered, it is returned instead.

+
§Examples
+

Create a new IPv6 socket and start listening.

+ +
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "[::1]:8080".parse().unwrap();
+    let socket = TcpSocket::new_v6()?;
+    socket.bind(addr)?;
+
+    let listener = socket.listen(128)?;
+    Ok(())
+}
+

pub fn set_keepalive(&self, keepalive: bool) -> Result<(), Error>

Sets value for the SO_KEEPALIVE option on this socket.

+

pub fn keepalive(&self) -> Result<bool, Error>

Gets the value of the SO_KEEPALIVE option on this socket.

+

pub fn set_reuseaddr(&self, reuseaddr: bool) -> Result<(), Error>

Allows the socket to bind to an in-use address.

+

Behavior is platform specific. Refer to the target platform’s +documentation for more details.

+
§Examples
+
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    socket.set_reuseaddr(true)?;
+    socket.bind(addr)?;
+
+    let listener = socket.listen(1024)?;
+
+    Ok(())
+}
+

pub fn reuseaddr(&self) -> Result<bool, Error>

Retrieves the value set for SO_REUSEADDR on this socket.

+
§Examples
+
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    socket.set_reuseaddr(true)?;
+    assert!(socket.reuseaddr().unwrap());
+    socket.bind(addr)?;
+
+    let listener = socket.listen(1024)?;
+    Ok(())
+}
+

pub fn set_reuseport(&self, reuseport: bool) -> Result<(), Error>

Allows the socket to bind to an in-use port. Only available for unix systems +(excluding Solaris & Illumos).

+

Behavior is platform specific. Refer to the target platform’s +documentation for more details.

+
§Examples
+
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    socket.set_reuseport(true)?;
+    socket.bind(addr)?;
+
+    let listener = socket.listen(1024)?;
+    Ok(())
+}
+

pub fn reuseport(&self) -> Result<bool, Error>

Allows the socket to bind to an in-use port. Only available for unix systems +(excluding Solaris & Illumos).

+

Behavior is platform specific. Refer to the target platform’s +documentation for more details.

+
§Examples
+
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    socket.set_reuseport(true)?;
+    assert!(socket.reuseport().unwrap());
+    socket.bind(addr)?;
+
+    let listener = socket.listen(1024)?;
+    Ok(())
+}
+

pub fn set_send_buffer_size(&self, size: u32) -> Result<(), Error>

Sets the size of the TCP send buffer on this socket.

+

On most operating systems, this sets the SO_SNDBUF socket option.

+

pub fn send_buffer_size(&self) -> Result<u32, Error>

Returns the size of the TCP send buffer for this socket.

+

On most operating systems, this is the value of the SO_SNDBUF socket +option.

+

Note that if set_send_buffer_size has been called on this socket +previously, the value returned by this function may not be the same as +the argument provided to set_send_buffer_size. This is for the +following reasons:

+
    +
  • Most operating systems have minimum and maximum allowed sizes for the +send buffer, and will clamp the provided value if it is below the +minimum or above the maximum. The minimum and maximum buffer sizes are +OS-dependent.
  • +
  • Linux will double the buffer size to account for internal bookkeeping +data, and returns the doubled value from getsockopt(2). As per man 7 socket: +
    +

    Sets or gets the maximum socket send buffer in bytes. The +kernel doubles this value (to allow space for bookkeeping +overhead) when it is set using setsockopt(2), and this doubled +value is returned by getsockopt(2).

    +
    +
  • +
+

pub fn set_recv_buffer_size(&self, size: u32) -> Result<(), Error>

Sets the size of the TCP receive buffer on this socket.

+

On most operating systems, this sets the SO_RCVBUF socket option.

+

pub fn recv_buffer_size(&self) -> Result<u32, Error>

Returns the size of the TCP receive buffer for this socket.

+

On most operating systems, this is the value of the SO_RCVBUF socket +option.

+

Note that if set_recv_buffer_size has been called on this socket +previously, the value returned by this function may not be the same as +the argument provided to set_send_buffer_size. This is for the +following reasons:

+
    +
  • Most operating systems have minimum and maximum allowed sizes for the +receive buffer, and will clamp the provided value if it is below the +minimum or above the maximum. The minimum and maximum buffer sizes are +OS-dependent.
  • +
  • Linux will double the buffer size to account for internal bookkeeping +data, and returns the doubled value from getsockopt(2). As per man 7 socket: +
    +

    Sets or gets the maximum socket send buffer in bytes. The +kernel doubles this value (to allow space for bookkeeping +overhead) when it is set using setsockopt(2), and this doubled +value is returned by getsockopt(2).

    +
    +
  • +
+

pub fn set_linger(&self, dur: Option<Duration>) -> Result<(), Error>

Sets the linger duration of this socket by setting the SO_LINGER option.

+

This option controls the action taken when a stream has unsent messages and the stream is +closed. If SO_LINGER is set, the system shall block the process until it can transmit the +data or until the time expires.

+

If SO_LINGER is not specified, and the socket is closed, the system handles the call in a +way that allows the process to continue as quickly as possible.

+

pub fn linger(&self) -> Result<Option<Duration>, Error>

Reads the linger duration for this socket by getting the SO_LINGER +option.

+

For more information about this option, see set_linger.

+

pub fn set_nodelay(&self, nodelay: bool) -> Result<(), Error>

Sets the value of the TCP_NODELAY option on this socket.

+

If set, this option disables the Nagle algorithm. This means that segments are always +sent as soon as possible, even if there is only a small amount of data. When not set, +data is buffered until there is a sufficient amount to send out, thereby avoiding +the frequent sending of small packets.

+
§Examples
+
use tokio::net::TcpSocket;
+
+let socket = TcpSocket::new_v4()?;
+
+println!("{:?}", socket.nodelay()?);
+

pub fn nodelay(&self) -> Result<bool, Error>

Gets the value of the TCP_NODELAY option on this socket.

+

For more information about this option, see set_nodelay.

+
§Examples
+
use tokio::net::TcpSocket;
+
+let stream = TcpSocket::new_v4()?;
+
+stream.set_nodelay(true)?;
+

pub fn tos(&self) -> Result<u32, Error>

Gets the value of the IP_TOS option for this socket.

+

For more information about this option, see set_tos.

+

NOTE: On Windows, IP_TOS is only supported on Windows 8+ or +Windows Server 2012+.

+

pub fn set_tos(&self, tos: u32) -> Result<(), Error>

Sets the value for the IP_TOS option on this socket.

+

This value sets the type-of-service field that is used in every packet +sent from this socket.

+

NOTE: On Windows, IP_TOS is only supported on Windows 8+ or +Windows Server 2012+.

+

pub fn device(&self) -> Result<Option<Vec<u8>>, Error>

Gets the value for the SO_BINDTODEVICE option on this socket

+

This value gets the socket binded device’s interface name.

+

pub fn bind_device(&self, interface: Option<&[u8]>) -> Result<(), Error>

Sets the value for the SO_BINDTODEVICE option on this socket

+

If a socket is bound to an interface, only packets received from that +particular interface are processed by the socket. Note that this only +works for some socket types, particularly AF_INET sockets.

+

If interface is None or an empty string it removes the binding.

+

pub fn local_addr(&self) -> Result<SocketAddr, Error>

Gets the local address of this socket.

+

Will fail on windows if called before bind.

+
§Examples
+
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    socket.bind(addr)?;
+    assert_eq!(socket.local_addr().unwrap().to_string(), "127.0.0.1:8080");
+    let listener = socket.listen(1024)?;
+    Ok(())
+}
+

pub fn take_error(&self) -> Result<Option<Error>, Error>

Returns the value of the SO_ERROR option.

+

pub fn bind(&self, addr: SocketAddr) -> Result<(), Error>

Binds the socket to the given address.

+

This calls the bind(2) operating-system function. Behavior is +platform specific. Refer to the target platform’s documentation for more +details.

+
§Examples
+

Bind a socket before listening.

+ +
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    socket.bind(addr)?;
+
+    let listener = socket.listen(1024)?;
+
+    Ok(())
+}
+

pub async fn connect(self, addr: SocketAddr) -> Result<TcpStream, Error>

Establishes a TCP connection with a peer at the specified socket address.

+

The TcpSocket is consumed. Once the connection is established, a +connected TcpStream is returned. If the connection fails, the +encountered error is returned.

+

This calls the connect(2) operating-system function. Behavior is +platform specific. Refer to the target platform’s documentation for more +details.

+
§Examples
+

Connecting to a peer.

+ +
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    let stream = socket.connect(addr).await?;
+
+    Ok(())
+}
+

pub fn listen(self, backlog: u32) -> Result<TcpListener, Error>

Converts the socket into a TcpListener.

+

backlog defines the maximum number of pending connections are queued +by the operating system at any given time. Connection are removed from +the queue with TcpListener::accept. When the queue is full, the +operating-system will start rejecting connections.

+

This calls the listen(2) operating-system function, marking the socket +as a passive socket. Behavior is platform specific. Refer to the target +platform’s documentation for more details.

+
§Examples
+

Create a TcpListener.

+ +
use tokio::net::TcpSocket;
+
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let addr = "127.0.0.1:8080".parse().unwrap();
+
+    let socket = TcpSocket::new_v4()?;
+    socket.bind(addr)?;
+
+    let listener = socket.listen(1024)?;
+
+    Ok(())
+}
+

pub fn from_std_stream(std_stream: TcpStream) -> TcpSocket

Converts a std::net::TcpStream into a TcpSocket. The provided +socket must not have been connected prior to calling this function. This +function is typically used together with crates such as socket2 to +configure socket options that are not available on TcpSocket.

+
§Notes
+

The caller is responsible for ensuring that the socket is in +non-blocking mode. Otherwise all I/O operations on the socket +will block the thread, which will cause unexpected behavior. +Non-blocking mode can be set using set_nonblocking.

+
§Examples
+
use tokio::net::TcpSocket;
+use socket2::{Domain, Socket, Type};
+
+#[tokio::main]
+async fn main() -> std::io::Result<()> {
+    let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
+    socket2_socket.set_nonblocking(true)?;
+
+    let socket = TcpSocket::from_std_stream(socket2_socket.into());
+
+    Ok(())
+}
+

Trait Implementations§

§

impl AsFd for TcpSocket

§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
§

impl AsRawFd for TcpSocket

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl Debug for TcpSocket

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl FromRawFd for TcpSocket

§

unsafe fn from_raw_fd(fd: i32) -> TcpSocket

Converts a RawFd to a TcpSocket.

+
§Notes
+

The caller is responsible for ensuring that the socket is in +non-blocking mode.

+
§

impl IntoRawFd for TcpSocket

§

fn into_raw_fd(self) -> i32

Consumes this object, returning the raw underlying file descriptor. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/net/struct.TcpStream.html b/actix_rt/net/struct.TcpStream.html new file mode 100644 index 00000000..a68b69c2 --- /dev/null +++ b/actix_rt/net/struct.TcpStream.html @@ -0,0 +1,718 @@ +TcpStream in actix_rt::net - Rust
actix_rt::net

Struct TcpStream

pub struct TcpStream { /* private fields */ }
Expand description

A TCP stream between a local and a remote socket.

+

A TCP stream can either be created by connecting to an endpoint, via the +connect method, or by accepting a connection from a listener. A +TCP stream can also be created via the TcpSocket type.

+

Reading and writing to a TcpStream is usually done using the +convenience methods found on the AsyncReadExt and AsyncWriteExt +traits.

+

§Examples

+
use tokio::net::TcpStream;
+use tokio::io::AsyncWriteExt;
+use std::error::Error;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    // Write some data.
+    stream.write_all(b"hello world!").await?;
+
+    Ok(())
+}
+

The write_all method is defined on the AsyncWriteExt trait.

+

To shut down the stream in the write direction, you can call the +shutdown() method. This will cause the other peer to receive a read of +length 0, indicating that no more data will be sent. This only closes +the stream in one direction.

+

Implementations§

§

impl TcpStream

pub async fn connect<A>(addr: A) -> Result<TcpStream, Error>
where + A: ToSocketAddrs,

Opens a TCP connection to a remote host.

+

addr is an address of the remote host. Anything which implements the +ToSocketAddrs trait can be supplied as the address. If addr +yields multiple addresses, connect will be attempted with each of the +addresses until a connection is successful. If none of the addresses +result in a successful connection, the error returned from the last +connection attempt (the last address) is returned.

+

To configure the socket before connecting, you can use the TcpSocket +type.

+
§Examples
+
use tokio::net::TcpStream;
+use tokio::io::AsyncWriteExt;
+use std::error::Error;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    // Write some data.
+    stream.write_all(b"hello world!").await?;
+
+    Ok(())
+}
+

The write_all method is defined on the AsyncWriteExt trait.

+

pub fn from_std(stream: TcpStream) -> Result<TcpStream, Error>

Creates new TcpStream from a std::net::TcpStream.

+

This function is intended to be used to wrap a TCP stream from the +standard library in the Tokio equivalent.

+
§Notes
+

The caller is responsible for ensuring that the stream is in +non-blocking mode. Otherwise all I/O operations on the stream +will block the thread, which will cause unexpected behavior. +Non-blocking mode can be set using set_nonblocking.

+
§Examples
+
use std::error::Error;
+use tokio::net::TcpStream;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let std_stream = std::net::TcpStream::connect("127.0.0.1:34254")?;
+    std_stream.set_nonblocking(true)?;
+    let stream = TcpStream::from_std(std_stream)?;
+    Ok(())
+}
+
§Panics
+

This function panics if it is not called from within a runtime with +IO enabled.

+

The runtime is usually set implicitly when this function is called +from a future driven by a tokio runtime, otherwise runtime can be set +explicitly with Runtime::enter function.

+

pub fn into_std(self) -> Result<TcpStream, Error>

Turns a tokio::net::TcpStream into a std::net::TcpStream.

+

The returned std::net::TcpStream will have nonblocking mode set as true. +Use set_nonblocking to change the blocking mode if needed.

+
§Examples
+
use std::error::Error;
+use std::io::Read;
+use tokio::net::TcpListener;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let mut data = [0u8; 12];
+    let listener = TcpListener::bind("127.0.0.1:34254").await?;
+    let (tokio_tcp_stream, _) = listener.accept().await?;
+    let mut std_tcp_stream = tokio_tcp_stream.into_std()?;
+    std_tcp_stream.set_nonblocking(false)?;
+    std_tcp_stream.read_exact(&mut data)?;
+    Ok(())
+}
+

pub fn local_addr(&self) -> Result<SocketAddr, Error>

Returns the local address that this stream is bound to.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+println!("{:?}", stream.local_addr()?);
+

pub fn take_error(&self) -> Result<Option<Error>, Error>

Returns the value of the SO_ERROR option.

+

pub fn peer_addr(&self) -> Result<SocketAddr, Error>

Returns the remote address that this stream is connected to.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+println!("{:?}", stream.peer_addr()?);
+

pub fn poll_peek( + &self, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<usize, Error>>

Attempts to receive data on the socket, without removing that data from +the queue, registering the current task for wakeup if data is not yet +available.

+

Note that on multiple calls to poll_peek, poll_read or +poll_read_ready, only the Waker from the Context passed to the +most recent call is scheduled to receive a wakeup. (However, +poll_write retains a second, independent waker.)

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if data is not yet available.
  • +
  • Poll::Ready(Ok(n)) if data is available. n is the number of bytes peeked.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+
§Examples
+
use tokio::io::{self, ReadBuf};
+use tokio::net::TcpStream;
+
+use futures::future::poll_fn;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let stream = TcpStream::connect("127.0.0.1:8000").await?;
+    let mut buf = [0; 10];
+    let mut buf = ReadBuf::new(&mut buf);
+
+    poll_fn(|cx| {
+        stream.poll_peek(cx, &mut buf)
+    }).await?;
+
+    Ok(())
+}
+

pub async fn ready(&self, interest: Interest) -> Result<Ready, Error>

Waits for any of the requested ready states.

+

This function is usually paired with try_read() or try_write(). It +can be used to concurrently read / write to the same socket on a single +task without splitting the socket.

+

The function may complete without the socket being ready. This is a +false-positive and attempting an operation will return with +io::ErrorKind::WouldBlock. The function can also return with an empty +Ready set, so you should always check the returned value and possibly +wait again if the requested states are not set.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read or write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+

Concurrently read and write to the stream on the same task without +splitting.

+ +
use tokio::io::Interest;
+use tokio::net::TcpStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    loop {
+        let ready = stream.ready(Interest::READABLE | Interest::WRITABLE).await?;
+
+        if ready.is_readable() {
+            let mut data = vec![0; 1024];
+            // Try to read data, this may still fail with `WouldBlock`
+            // if the readiness event is a false positive.
+            match stream.try_read(&mut data) {
+                Ok(n) => {
+                    println!("read {} bytes", n);
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                    continue;
+                }
+                Err(e) => {
+                    return Err(e.into());
+                }
+            }
+
+        }
+
+        if ready.is_writable() {
+            // Try to write data, this may still fail with `WouldBlock`
+            // if the readiness event is a false positive.
+            match stream.try_write(b"hello world") {
+                Ok(n) => {
+                    println!("write {} bytes", n);
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                    continue
+                }
+                Err(e) => {
+                    return Err(e.into());
+                }
+            }
+        }
+    }
+}
+

pub async fn readable(&self) -> Result<(), Error>

Waits for the socket to become readable.

+

This function is equivalent to ready(Interest::READABLE) and is usually +paired with try_read().

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::TcpStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    let mut msg = vec![0; 1024];
+
+    loop {
+        // Wait for the socket to be readable
+        stream.readable().await?;
+
+        // Try to read data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_read(&mut msg) {
+            Ok(n) => {
+                msg.truncate(n);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    println!("GOT = {:?}", msg);
+    Ok(())
+}
+

pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for read readiness.

+

If the tcp stream is not currently ready for reading, this method will +store a clone of the Waker from the provided Context. When the tcp +stream becomes ready for reading, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_read_ready, poll_read or +poll_peek, only the Waker from the Context passed to the most +recent call is scheduled to receive a wakeup. (However, +poll_write_ready retains a second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via readable is not feasible. Where possible, using readable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the tcp stream is not ready for reading.
  • +
  • Poll::Ready(Ok(())) if the tcp stream is ready for reading.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_read(&self, buf: &mut [u8]) -> Result<usize, Error>

Tries to read data from the stream into the provided buffer, returning how +many bytes were read.

+

Receives any pending data from the socket but does not wait for new data +to arrive. On success, returns the number of bytes read. Because +try_read() is non-blocking, the buffer does not have to be stored by +the async task and can exist entirely on the stack.

+

Usually, readable() or ready() is used with this function.

+
§Return
+

If data is successfully read, Ok(n) is returned, where n is the +number of bytes read. If n is 0, then it can indicate one of two scenarios:

+
    +
  1. The stream’s read half is closed and will no longer yield data.
  2. +
  3. The specified buffer was 0 bytes in length.
  4. +
+

If the stream is not ready to read data, +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::TcpStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    loop {
+        // Wait for the socket to be readable
+        stream.readable().await?;
+
+        // Creating the buffer **after** the `await` prevents it from
+        // being stored in the async task.
+        let mut buf = [0; 4096];
+
+        // Try to read data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_read(&mut buf) {
+            Ok(0) => break,
+            Ok(n) => {
+                println!("read {} bytes", n);
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_read_vectored( + &self, + bufs: &mut [IoSliceMut<'_>], +) -> Result<usize, Error>

Tries to read data from the stream into the provided buffers, returning +how many bytes were read.

+

Data is copied to fill each buffer in order, with the final buffer +written to possibly being only partially filled. This method behaves +equivalently to a single call to try_read() with concatenated +buffers.

+

Receives any pending data from the socket but does not wait for new data +to arrive. On success, returns the number of bytes read. Because +try_read_vectored() is non-blocking, the buffer does not have to be +stored by the async task and can exist entirely on the stack.

+

Usually, readable() or ready() is used with this function.

+
§Return
+

If data is successfully read, Ok(n) is returned, where n is the +number of bytes read. Ok(0) indicates the stream’s read half is closed +and will no longer yield data. If the stream is not ready to read data +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::TcpStream;
+use std::error::Error;
+use std::io::{self, IoSliceMut};
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    loop {
+        // Wait for the socket to be readable
+        stream.readable().await?;
+
+        // Creating the buffer **after** the `await` prevents it from
+        // being stored in the async task.
+        let mut buf_a = [0; 512];
+        let mut buf_b = [0; 1024];
+        let mut bufs = [
+            IoSliceMut::new(&mut buf_a),
+            IoSliceMut::new(&mut buf_b),
+        ];
+
+        // Try to read data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_read_vectored(&mut bufs) {
+            Ok(0) => break,
+            Ok(n) => {
+                println!("read {} bytes", n);
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub async fn writable(&self) -> Result<(), Error>

Waits for the socket to become writable.

+

This function is equivalent to ready(Interest::WRITABLE) and is usually +paired with try_write().

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::TcpStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    loop {
+        // Wait for the socket to be writable
+        stream.writable().await?;
+
+        // Try to write data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_write(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for write readiness.

+

If the tcp stream is not currently ready for writing, this method will +store a clone of the Waker from the provided Context. When the tcp +stream becomes ready for writing, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_write_ready or poll_write, only +the Waker from the Context passed to the most recent call is +scheduled to receive a wakeup. (However, poll_read_ready retains a +second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via writable is not feasible. Where possible, using writable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the tcp stream is not ready for writing.
  • +
  • Poll::Ready(Ok(())) if the tcp stream is ready for writing.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_write(&self, buf: &[u8]) -> Result<usize, Error>

Try to write a buffer to the stream, returning how many bytes were +written.

+

The function will attempt to write the entire contents of buf, but +only part of the buffer may be written.

+

This function is usually paired with writable().

+
§Return
+

If data is successfully written, Ok(n) is returned, where n is the +number of bytes written. If the stream is not ready to write data, +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::TcpStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    loop {
+        // Wait for the socket to be writable
+        stream.writable().await?;
+
+        // Try to write data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_write(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_write_vectored(&self, bufs: &[IoSlice<'_>]) -> Result<usize, Error>

Tries to write several buffers to the stream, returning how many bytes +were written.

+

Data is written from each buffer in order, with the final buffer read +from possible being only partially consumed. This method behaves +equivalently to a single call to try_write() with concatenated +buffers.

+

This function is usually paired with writable().

+
§Return
+

If data is successfully written, Ok(n) is returned, where n is the +number of bytes written. If the stream is not ready to write data, +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::TcpStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")];
+
+    loop {
+        // Wait for the socket to be writable
+        stream.writable().await?;
+
+        // Try to write data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_write_vectored(&bufs) {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_io<R>( + &self, + interest: Interest, + f: impl FnOnce() -> Result<R, Error>, +) -> Result<R, Error>

Tries to read or write from the socket using a user-provided IO operation.

+

If the socket is ready, the provided closure is called. The closure +should attempt to perform IO operation on the socket by manually +calling the appropriate syscall. If the operation fails because the +socket is not actually ready, then the closure should return a +WouldBlock error and the readiness flag is cleared. The return value +of the closure is then returned by try_io.

+

If the socket is not ready, then the closure is not called +and a WouldBlock error is returned.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio TcpStream type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

Usually, readable(), writable() or ready() is used with this function.

+

pub async fn async_io<R>( + &self, + interest: Interest, + f: impl FnMut() -> Result<R, Error>, +) -> Result<R, Error>

Reads or writes from the socket using a user-provided IO operation.

+

The readiness of the socket is awaited and when the socket is ready, +the provided closure is called. The closure should attempt to perform +IO operation on the socket by manually calling the appropriate syscall. +If the operation fails because the socket is not actually ready, +then the closure should return a WouldBlock error. In such case the +readiness flag is cleared and the socket readiness is awaited again. +This loop is repeated until the closure returns an Ok or an error +other than WouldBlock.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio TcpStream type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

pub async fn peek(&self, buf: &mut [u8]) -> Result<usize, Error>

Receives data on the socket from the remote address to which it is +connected, without removing that data from the queue. On success, +returns the number of bytes peeked.

+

Successive calls return the same data. This is accomplished by passing +MSG_PEEK as a flag to the underlying recv system call.

+
§Examples
+
use tokio::net::TcpStream;
+use tokio::io::AsyncReadExt;
+use std::error::Error;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+    let mut b1 = [0; 10];
+    let mut b2 = [0; 10];
+
+    // Peek at the data
+    let n = stream.peek(&mut b1).await?;
+
+    // Read the data
+    assert_eq!(n, stream.read(&mut b2[..n]).await?);
+    assert_eq!(&b1[..n], &b2[..n]);
+
+    Ok(())
+}
+

The read method is defined on the AsyncReadExt trait.

+

pub fn nodelay(&self) -> Result<bool, Error>

Gets the value of the TCP_NODELAY option on this socket.

+

For more information about this option, see set_nodelay.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+println!("{:?}", stream.nodelay()?);
+

pub fn set_nodelay(&self, nodelay: bool) -> Result<(), Error>

Sets the value of the TCP_NODELAY option on this socket.

+

If set, this option disables the Nagle algorithm. This means that +segments are always sent as soon as possible, even if there is only a +small amount of data. When not set, data is buffered until there is a +sufficient amount to send out, thereby avoiding the frequent sending of +small packets.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+stream.set_nodelay(true)?;
+

pub fn linger(&self) -> Result<Option<Duration>, Error>

Reads the linger duration for this socket by getting the SO_LINGER +option.

+

For more information about this option, see set_linger.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+println!("{:?}", stream.linger()?);
+

pub fn set_linger(&self, dur: Option<Duration>) -> Result<(), Error>

Sets the linger duration of this socket by setting the SO_LINGER option.

+

This option controls the action taken when a stream has unsent messages and the stream is +closed. If SO_LINGER is set, the system shall block the process until it can transmit the +data or until the time expires.

+

If SO_LINGER is not specified, and the stream is closed, the system handles the call in a +way that allows the process to continue as quickly as possible.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+stream.set_linger(None)?;
+

pub fn ttl(&self) -> Result<u32, Error>

Gets the value of the IP_TTL option for this socket.

+

For more information about this option, see set_ttl.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+println!("{:?}", stream.ttl()?);
+

pub fn set_ttl(&self, ttl: u32) -> Result<(), Error>

Sets the value for the IP_TTL option on this socket.

+

This value sets the time-to-live field that is used in every packet sent +from this socket.

+
§Examples
+
use tokio::net::TcpStream;
+
+let stream = TcpStream::connect("127.0.0.1:8080").await?;
+
+stream.set_ttl(123)?;
+

pub fn split<'a>(&'a mut self) -> (ReadHalf<'a>, WriteHalf<'a>)

Splits a TcpStream into a read half and a write half, which can be used +to read and write the stream concurrently.

+

This method is more efficient than into_split, but the halves cannot be +moved into independently spawned tasks.

+

pub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf)

Splits a TcpStream into a read half and a write half, which can be used +to read and write the stream concurrently.

+

Unlike split, the owned halves can be moved to separate tasks, however +this comes at the cost of a heap allocation.

+

Note: Dropping the write half will shut down the write half of the TCP +stream. This is equivalent to calling shutdown() on the TcpStream.

+

Trait Implementations§

§

impl AsFd for TcpStream

§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
§

impl AsRawFd for TcpStream

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl AsyncRead for TcpStream

§

fn poll_read( + self: Pin<&mut TcpStream>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
§

impl AsyncWrite for TcpStream

§

fn poll_write( + self: Pin<&mut TcpStream>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Attempt to write bytes from buf into the object. Read more
§

fn poll_write_vectored( + self: Pin<&mut TcpStream>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
§

fn poll_flush( + self: Pin<&mut TcpStream>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
§

fn poll_shutdown( + self: Pin<&mut TcpStream>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

impl Debug for TcpStream

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl TryFrom<TcpStream> for TcpStream

§

fn try_from( + stream: TcpStream, +) -> Result<TcpStream, <TcpStream as TryFrom<TcpStream>>::Error>

Consumes stream, returning the tokio I/O object.

+

This is equivalent to +TcpStream::from_std(stream).

+
§

type Error = Error

The type returned in the event of a conversion error.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/net/struct.UdpSocket.html b/actix_rt/net/struct.UdpSocket.html new file mode 100644 index 00000000..64bb61c2 --- /dev/null +++ b/actix_rt/net/struct.UdpSocket.html @@ -0,0 +1,1030 @@ +UdpSocket in actix_rt::net - Rust
actix_rt::net

Struct UdpSocket

pub struct UdpSocket { /* private fields */ }
Expand description

A UDP socket.

+

UDP is “connectionless”, unlike TCP. Meaning, regardless of what address you’ve bound to, a UdpSocket +is free to communicate with many different remotes. In tokio there are basically two main ways to use UdpSocket:

+
    +
  • one to many: bind and use send_to +and recv_from to communicate with many different addresses
  • +
  • one to one: connect and associate with a single address, using send +and recv to communicate only with that remote address
  • +
+

This type does not provide a split method, because this functionality +can be achieved by instead wrapping the socket in an Arc. Note that +you do not need a Mutex to share the UdpSocket — an Arc<UdpSocket> +is enough. This is because all of the methods take &self instead of +&mut self. Once you have wrapped it in an Arc, you can call +.clone() on the Arc<UdpSocket> to get multiple shared handles to the +same socket. An example of such usage can be found further down.

+

§Streams

+

If you need to listen over UDP and produce a Stream, you can look +at UdpFramed.

+

§Example: one to many (bind)

+

Using bind we can create a simple echo server that sends and recv’s with many different clients:

+ +
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let sock = UdpSocket::bind("0.0.0.0:8080").await?;
+    let mut buf = [0; 1024];
+    loop {
+        let (len, addr) = sock.recv_from(&mut buf).await?;
+        println!("{:?} bytes received from {:?}", len, addr);
+
+        let len = sock.send_to(&buf[..len], addr).await?;
+        println!("{:?} bytes sent", len);
+    }
+}
+

§Example: one to one (connect)

+

Or using connect we can echo with a single remote address using send and recv:

+ +
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let sock = UdpSocket::bind("0.0.0.0:8080").await?;
+
+    let remote_addr = "127.0.0.1:59611";
+    sock.connect(remote_addr).await?;
+    let mut buf = [0; 1024];
+    loop {
+        let len = sock.recv(&mut buf).await?;
+        println!("{:?} bytes received from {:?}", len, remote_addr);
+
+        let len = sock.send(&buf[..len]).await?;
+        println!("{:?} bytes sent", len);
+    }
+}
+

§Example: Splitting with Arc

+

Because send_to and recv_from take &self. It’s perfectly alright +to use an Arc<UdpSocket> and share the references to multiple tasks. +Here is a similar “echo” example that supports concurrent +sending/receiving:

+ +
use tokio::{net::UdpSocket, sync::mpsc};
+use std::{io, net::SocketAddr, sync::Arc};
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let sock = UdpSocket::bind("0.0.0.0:8080".parse::<SocketAddr>().unwrap()).await?;
+    let r = Arc::new(sock);
+    let s = r.clone();
+    let (tx, mut rx) = mpsc::channel::<(Vec<u8>, SocketAddr)>(1_000);
+
+    tokio::spawn(async move {
+        while let Some((bytes, addr)) = rx.recv().await {
+            let len = s.send_to(&bytes, &addr).await.unwrap();
+            println!("{:?} bytes sent", len);
+        }
+    });
+
+    let mut buf = [0; 1024];
+    loop {
+        let (len, addr) = r.recv_from(&mut buf).await?;
+        println!("{:?} bytes received from {:?}", len, addr);
+        tx.send((buf[..len].to_vec(), addr)).await.unwrap();
+    }
+}
+

Implementations§

§

impl UdpSocket

pub async fn bind<A>(addr: A) -> Result<UdpSocket, Error>
where + A: ToSocketAddrs,

This function will create a new UDP socket and attempt to bind it to +the addr provided.

+

Binding with a port number of 0 will request that the OS assigns a port +to this listener. The port allocated can be queried via the local_addr +method.

+
§Example
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let sock = UdpSocket::bind("0.0.0.0:8080").await?;
+    // use `sock`
+    Ok(())
+}
+

pub fn from_std(socket: UdpSocket) -> Result<UdpSocket, Error>

Creates new UdpSocket from a previously bound std::net::UdpSocket.

+

This function is intended to be used to wrap a UDP socket from the +standard library in the Tokio equivalent.

+

This can be used in conjunction with socket2’s Socket interface to +configure a socket before it’s handed off, such as setting options like +reuse_address or binding to multiple addresses.

+
§Notes
+

The caller is responsible for ensuring that the socket is in +non-blocking mode. Otherwise all I/O operations on the socket +will block the thread, which will cause unexpected behavior. +Non-blocking mode can be set using set_nonblocking.

+
§Panics
+

This function panics if thread-local runtime is not set.

+

The runtime is usually set implicitly when this function is called +from a future driven by a tokio runtime, otherwise runtime can be set +explicitly with Runtime::enter function.

+
§Example
+
use tokio::net::UdpSocket;
+
+let addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
+let std_sock = std::net::UdpSocket::bind(addr)?;
+std_sock.set_nonblocking(true)?;
+let sock = UdpSocket::from_std(std_sock)?;
+// use `sock`
+

pub fn into_std(self) -> Result<UdpSocket, Error>

Turns a tokio::net::UdpSocket into a std::net::UdpSocket.

+

The returned std::net::UdpSocket will have nonblocking mode set as +true. Use set_nonblocking to change the blocking mode if needed.

+
§Examples
+
use std::error::Error;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let tokio_socket = tokio::net::UdpSocket::bind("127.0.0.1:0").await?;
+    let std_socket = tokio_socket.into_std()?;
+    std_socket.set_nonblocking(false)?;
+    Ok(())
+}
+

pub fn local_addr(&self) -> Result<SocketAddr, Error>

Returns the local address that this socket is bound to.

+
§Example
+
use tokio::net::UdpSocket;
+
+let addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
+let sock = UdpSocket::bind(addr).await?;
+// the address the socket is bound to
+let local_addr = sock.local_addr()?;
+

pub fn peer_addr(&self) -> Result<SocketAddr, Error>

Returns the socket address of the remote peer this socket was connected to.

+
§Example
+
use tokio::net::UdpSocket;
+
+let addr = "0.0.0.0:8080".parse::<SocketAddr>().unwrap();
+let peer = "127.0.0.1:11100".parse::<SocketAddr>().unwrap();
+let sock = UdpSocket::bind(addr).await?;
+sock.connect(peer).await?;
+assert_eq!(peer, sock.peer_addr()?);
+

pub async fn connect<A>(&self, addr: A) -> Result<(), Error>
where + A: ToSocketAddrs,

Connects the UDP socket setting the default destination for send() and +limiting packets that are read via recv from the address specified in +addr.

+
§Example
+
use tokio::net::UdpSocket;
+
+let sock = UdpSocket::bind("0.0.0.0:8080".parse::<SocketAddr>().unwrap()).await?;
+
+let remote_addr = "127.0.0.1:59600".parse::<SocketAddr>().unwrap();
+sock.connect(remote_addr).await?;
+let mut buf = [0u8; 32];
+// recv from remote_addr
+let len = sock.recv(&mut buf).await?;
+// send to remote_addr
+let _len = sock.send(&buf[..len]).await?;
+

pub async fn ready(&self, interest: Interest) -> Result<Ready, Error>

Waits for any of the requested ready states.

+

This function is usually paired with try_recv() or try_send(). It +can be used to concurrently recv / send to the same socket on a single +task without splitting the socket.

+

The function may complete without the socket being ready. This is a +false-positive and attempting an operation will return with +io::ErrorKind::WouldBlock. The function can also return with an empty +Ready set, so you should always check the returned value and possibly +wait again if the requested states are not set.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read or write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+

Concurrently receive from and send to the socket on the same task +without splitting.

+ +
use tokio::io::{self, Interest};
+use tokio::net::UdpSocket;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+    socket.connect("127.0.0.1:8081").await?;
+
+    loop {
+        let ready = socket.ready(Interest::READABLE | Interest::WRITABLE).await?;
+
+        if ready.is_readable() {
+            // The buffer is **not** included in the async task and will only exist
+            // on the stack.
+            let mut data = [0; 1024];
+            match socket.try_recv(&mut data[..]) {
+                Ok(n) => {
+                    println!("received {:?}", &data[..n]);
+                }
+                // False-positive, continue
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
+                Err(e) => {
+                    return Err(e);
+                }
+            }
+        }
+
+        if ready.is_writable() {
+            // Write some data
+            match socket.try_send(b"hello world") {
+                Ok(n) => {
+                    println!("sent {} bytes", n);
+                }
+                // False-positive, continue
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
+                Err(e) => {
+                    return Err(e);
+                }
+            }
+        }
+    }
+}
+

pub async fn writable(&self) -> Result<(), Error>

Waits for the socket to become writable.

+

This function is equivalent to ready(Interest::WRITABLE) and is +usually paired with try_send() or try_send_to().

+

The function may complete without the socket being writable. This is a +false-positive and attempting a try_send() will return with +io::ErrorKind::WouldBlock.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Bind socket
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+    socket.connect("127.0.0.1:8081").await?;
+
+    loop {
+        // Wait for the socket to be writable
+        socket.writable().await?;
+
+        // Try to send data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_send(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn poll_send_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for write/send readiness.

+

If the udp stream is not currently ready for sending, this method will +store a clone of the Waker from the provided Context. When the udp +stream becomes ready for sending, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_send_ready or poll_send, only +the Waker from the Context passed to the most recent call is +scheduled to receive a wakeup. (However, poll_recv_ready retains a +second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via writable is not feasible. Where possible, using writable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the udp stream is not ready for writing.
  • +
  • Poll::Ready(Ok(())) if the udp stream is ready for writing.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub async fn send(&self, buf: &[u8]) -> Result<usize, Error>

Sends data on the socket to the remote address that the socket is +connected to.

+

The connect method will connect this socket to a remote address. +This method will fail if the socket is not connected.

+
§Return
+

On success, the number of bytes sent is returned, otherwise, the +encountered error is returned.

+
§Cancel safety
+

This method is cancel safe. If send is used as the event in a +tokio::select! statement and some other branch +completes first, then it is guaranteed that the message was not sent.

+
§Examples
+
use tokio::io;
+use tokio::net::UdpSocket;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Bind socket
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+    socket.connect("127.0.0.1:8081").await?;
+
+    // Send a message
+    socket.send(b"hello world").await?;
+
+    Ok(())
+}
+

pub fn poll_send( + &self, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Attempts to send data on the socket to the remote address to which it +was previously connected.

+

The connect method will connect this socket to a remote address. +This method will fail if the socket is not connected.

+

Note that on multiple calls to a poll_* method in the send direction, +only the Waker from the Context passed to the most recent call will +be scheduled to receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not available to write
  • +
  • Poll::Ready(Ok(n)) n is the number of bytes sent
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_send(&self, buf: &[u8]) -> Result<usize, Error>

Tries to send data on the socket to the remote address to which it is +connected.

+

When the socket buffer is full, Err(io::ErrorKind::WouldBlock) is +returned. This function is usually paired with writable().

+
§Returns
+

If successful, Ok(n) is returned, where n is the number of bytes +sent. If the socket is not ready to send data, +Err(ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Bind a UDP socket
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+
+    // Connect to a peer
+    socket.connect("127.0.0.1:8081").await?;
+
+    loop {
+        // Wait for the socket to be writable
+        socket.writable().await?;
+
+        // Try to send data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_send(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub async fn readable(&self) -> Result<(), Error>

Waits for the socket to become readable.

+

This function is equivalent to ready(Interest::READABLE) and is usually +paired with try_recv().

+

The function may complete without the socket being readable. This is a +false-positive and attempting a try_recv() will return with +io::ErrorKind::WouldBlock.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Connect to a peer
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+    socket.connect("127.0.0.1:8081").await?;
+
+    loop {
+        // Wait for the socket to be readable
+        socket.readable().await?;
+
+        // The buffer is **not** included in the async task and will
+        // only exist on the stack.
+        let mut buf = [0; 1024];
+
+        // Try to recv data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_recv(&mut buf) {
+            Ok(n) => {
+                println!("GOT {:?}", &buf[..n]);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn poll_recv_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for read/receive readiness.

+

If the udp stream is not currently ready for receiving, this method will +store a clone of the Waker from the provided Context. When the udp +socket becomes ready for reading, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_recv_ready, poll_recv or +poll_peek, only the Waker from the Context passed to the most +recent call is scheduled to receive a wakeup. (However, +poll_send_ready retains a second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via readable is not feasible. Where possible, using readable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the udp stream is not ready for reading.
  • +
  • Poll::Ready(Ok(())) if the udp stream is ready for reading.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub async fn recv(&self, buf: &mut [u8]) -> Result<usize, Error>

Receives a single datagram message on the socket from the remote address +to which it is connected. On success, returns the number of bytes read.

+

The function must be called with valid byte array buf of sufficient +size to hold the message bytes. If a message is too long to fit in the +supplied buffer, excess bytes may be discarded.

+

The connect method will connect this socket to a remote address. +This method will fail if the socket is not connected.

+
§Cancel safety
+

This method is cancel safe. If recv is used as the event in a +tokio::select! statement and some other branch +completes first, it is guaranteed that no messages were received on this +socket.

+ +
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Bind socket
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+    socket.connect("127.0.0.1:8081").await?;
+
+    let mut buf = vec![0; 10];
+    let n = socket.recv(&mut buf).await?;
+
+    println!("received {} bytes {:?}", n, &buf[..n]);
+
+    Ok(())
+}
+

pub fn poll_recv( + &self, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to receive a single datagram message on the socket from the remote +address to which it is connected.

+

The connect method will connect this socket to a remote address. This method +resolves to an error if the socket is not connected.

+

Note that on multiple calls to a poll_* method in the recv direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready to read
  • +
  • Poll::Ready(Ok(())) reads data ReadBuf if the socket is ready
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_recv(&self, buf: &mut [u8]) -> Result<usize, Error>

Tries to receive a single datagram message on the socket from the remote +address to which it is connected. On success, returns the number of +bytes read.

+

This method must be called with valid byte array buf of sufficient size +to hold the message bytes. If a message is too long to fit in the +supplied buffer, excess bytes may be discarded.

+

When there is no pending data, Err(io::ErrorKind::WouldBlock) is +returned. This function is usually paired with readable().

+
§Examples
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Connect to a peer
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+    socket.connect("127.0.0.1:8081").await?;
+
+    loop {
+        // Wait for the socket to be readable
+        socket.readable().await?;
+
+        // The buffer is **not** included in the async task and will
+        // only exist on the stack.
+        let mut buf = [0; 1024];
+
+        // Try to recv data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_recv(&mut buf) {
+            Ok(n) => {
+                println!("GOT {:?}", &buf[..n]);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub async fn send_to<A>(&self, buf: &[u8], target: A) -> Result<usize, Error>
where + A: ToSocketAddrs,

Sends data on the socket to the given address. On success, returns the +number of bytes written.

+

Address type can be any implementor of ToSocketAddrs trait. See its +documentation for concrete examples.

+

It is possible for addr to yield multiple addresses, but send_to +will only send data to the first address yielded by addr.

+

This will return an error when the IP version of the local socket does +not match that returned from ToSocketAddrs.

+
§Cancel safety
+

This method is cancel safe. If send_to is used as the event in a +tokio::select! statement and some other branch +completes first, then it is guaranteed that the message was not sent.

+
§Example
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+    let len = socket.send_to(b"hello world", "127.0.0.1:8081").await?;
+
+    println!("Sent {} bytes", len);
+
+    Ok(())
+}
+

pub fn poll_send_to( + &self, + cx: &mut Context<'_>, + buf: &[u8], + target: SocketAddr, +) -> Poll<Result<usize, Error>>

Attempts to send data on the socket to a given address.

+

Note that on multiple calls to a poll_* method in the send direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready to write
  • +
  • Poll::Ready(Ok(n)) n is the number of bytes sent.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_send_to( + &self, + buf: &[u8], + target: SocketAddr, +) -> Result<usize, Error>

Tries to send data on the socket to the given address, but if the send is +blocked this will return right away.

+

This function is usually paired with writable().

+
§Returns
+

If successful, returns the number of bytes sent

+

Users should ensure that when the remote cannot receive, the +ErrorKind::WouldBlock is properly handled. An error can also occur +if the IP version of the socket does not match that of target.

+
§Example
+
use tokio::net::UdpSocket;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+
+    let dst = "127.0.0.1:8081".parse()?;
+
+    loop {
+        socket.writable().await?;
+
+        match socket.try_send_to(&b"hello world"[..], dst) {
+            Ok(sent) => {
+                println!("sent {} bytes", sent);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                // Writable false positive.
+                continue;
+            }
+            Err(e) => return Err(e.into()),
+        }
+    }
+
+    Ok(())
+}
+

pub async fn recv_from( + &self, + buf: &mut [u8], +) -> Result<(usize, SocketAddr), Error>

Receives a single datagram message on the socket. On success, returns +the number of bytes read and the origin.

+

The function must be called with valid byte array buf of sufficient +size to hold the message bytes. If a message is too long to fit in the +supplied buffer, excess bytes may be discarded.

+
§Cancel safety
+

This method is cancel safe. If recv_from is used as the event in a +tokio::select! statement and some other branch +completes first, it is guaranteed that no messages were received on this +socket.

+
§Example
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+
+    let mut buf = vec![0u8; 32];
+    let (len, addr) = socket.recv_from(&mut buf).await?;
+
+    println!("received {:?} bytes from {:?}", len, addr);
+
+    Ok(())
+}
+
§Notes
+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+

pub fn poll_recv_from( + &self, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<SocketAddr, Error>>

Attempts to receive a single datagram on the socket.

+

Note that on multiple calls to a poll_* method in the recv direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready to read
  • +
  • Poll::Ready(Ok(addr)) reads data from addr into ReadBuf if the socket is ready
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+
§Notes
+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+

pub fn try_recv_from( + &self, + buf: &mut [u8], +) -> Result<(usize, SocketAddr), Error>

Tries to receive a single datagram message on the socket. On success, +returns the number of bytes read and the origin.

+

This method must be called with valid byte array buf of sufficient size +to hold the message bytes. If a message is too long to fit in the +supplied buffer, excess bytes may be discarded.

+

When there is no pending data, Err(io::ErrorKind::WouldBlock) is +returned. This function is usually paired with readable().

+
§Notes
+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+
§Examples
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Connect to a peer
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+
+    loop {
+        // Wait for the socket to be readable
+        socket.readable().await?;
+
+        // The buffer is **not** included in the async task and will
+        // only exist on the stack.
+        let mut buf = [0; 1024];
+
+        // Try to recv data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_recv_from(&mut buf) {
+            Ok((n, _addr)) => {
+                println!("GOT {:?}", &buf[..n]);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_io<R>( + &self, + interest: Interest, + f: impl FnOnce() -> Result<R, Error>, +) -> Result<R, Error>

Tries to read or write from the socket using a user-provided IO operation.

+

If the socket is ready, the provided closure is called. The closure +should attempt to perform IO operation on the socket by manually +calling the appropriate syscall. If the operation fails because the +socket is not actually ready, then the closure should return a +WouldBlock error and the readiness flag is cleared. The return value +of the closure is then returned by try_io.

+

If the socket is not ready, then the closure is not called +and a WouldBlock error is returned.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio UdpSocket type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

Usually, readable(), writable() or ready() is used with this function.

+

pub async fn async_io<R>( + &self, + interest: Interest, + f: impl FnMut() -> Result<R, Error>, +) -> Result<R, Error>

Reads or writes from the socket using a user-provided IO operation.

+

The readiness of the socket is awaited and when the socket is ready, +the provided closure is called. The closure should attempt to perform +IO operation on the socket by manually calling the appropriate syscall. +If the operation fails because the socket is not actually ready, +then the closure should return a WouldBlock error. In such case the +readiness flag is cleared and the socket readiness is awaited again. +This loop is repeated until the closure returns an Ok or an error +other than WouldBlock.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio UdpSocket type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

pub async fn peek_from( + &self, + buf: &mut [u8], +) -> Result<(usize, SocketAddr), Error>

Receives data from the socket, without removing it from the input queue. +On success, returns the number of bytes read and the address from whence +the data came.

+
§Notes
+

On Windows, if the data is larger than the buffer specified, the buffer +is filled with the first part of the data, and peek_from returns the error +WSAEMSGSIZE(10040). The excess data is lost. +Make sure to always use a sufficiently large buffer to hold the +maximum UDP packet size, which can be up to 65536 bytes in size.

+

MacOS will return an error if you pass a zero-sized buffer.

+

If you’re merely interested in learning the sender of the data at the head of the queue, +try peek_sender.

+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+
§Examples
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let socket = UdpSocket::bind("127.0.0.1:8080").await?;
+
+    let mut buf = vec![0u8; 32];
+    let (len, addr) = socket.peek_from(&mut buf).await?;
+
+    println!("peeked {:?} bytes from {:?}", len, addr);
+
+    Ok(())
+}
+

pub fn poll_peek_from( + &self, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<SocketAddr, Error>>

Receives data from the socket, without removing it from the input queue. +On success, returns the sending address of the datagram.

+
§Notes
+

Note that on multiple calls to a poll_* method in the recv direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup

+

On Windows, if the data is larger than the buffer specified, the buffer +is filled with the first part of the data, and peek returns the error +WSAEMSGSIZE(10040). The excess data is lost. +Make sure to always use a sufficiently large buffer to hold the +maximum UDP packet size, which can be up to 65536 bytes in size.

+

MacOS will return an error if you pass a zero-sized buffer.

+

If you’re merely interested in learning the sender of the data at the head of the queue, +try poll_peek_sender.

+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready to read
  • +
  • Poll::Ready(Ok(addr)) reads data from addr into ReadBuf if the socket is ready
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_peek_from( + &self, + buf: &mut [u8], +) -> Result<(usize, SocketAddr), Error>

Tries to receive data on the socket without removing it from the input queue. +On success, returns the number of bytes read and the sending address of the +datagram.

+

When there is no pending data, Err(io::ErrorKind::WouldBlock) is +returned. This function is usually paired with readable().

+
§Notes
+

On Windows, if the data is larger than the buffer specified, the buffer +is filled with the first part of the data, and peek returns the error +WSAEMSGSIZE(10040). The excess data is lost. +Make sure to always use a sufficiently large buffer to hold the +maximum UDP packet size, which can be up to 65536 bytes in size.

+

MacOS will return an error if you pass a zero-sized buffer.

+

If you’re merely interested in learning the sender of the data at the head of the queue, +try try_peek_sender.

+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+

pub async fn peek_sender(&self) -> Result<SocketAddr, Error>

Retrieve the sender of the data at the head of the input queue, waiting if empty.

+

This is equivalent to calling peek_from with a zero-sized buffer, +but suppresses the WSAEMSGSIZE error on Windows and the “invalid argument” error on macOS.

+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+

pub fn poll_peek_sender( + &self, + cx: &mut Context<'_>, +) -> Poll<Result<SocketAddr, Error>>

Retrieve the sender of the data at the head of the input queue, +scheduling a wakeup if empty.

+

This is equivalent to calling poll_peek_from with a zero-sized buffer, +but suppresses the WSAEMSGSIZE error on Windows and the “invalid argument” error on macOS.

+
§Notes
+

Note that on multiple calls to a poll_* method in the recv direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup.

+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+

pub fn try_peek_sender(&self) -> Result<SocketAddr, Error>

Try to retrieve the sender of the data at the head of the input queue.

+

When there is no pending data, Err(io::ErrorKind::WouldBlock) is +returned. This function is usually paired with readable().

+

Note that the socket address cannot be implicitly trusted, because it is relatively +trivial to send a UDP datagram with a spoofed origin in a packet injection attack. +Because UDP is stateless and does not validate the origin of a packet, +the attacker does not need to be able to intercept traffic in order to interfere. +It is important to be aware of this when designing your application-level protocol.

+

pub fn broadcast(&self) -> Result<bool, Error>

Gets the value of the SO_BROADCAST option for this socket.

+

For more information about this option, see set_broadcast.

+

pub fn set_broadcast(&self, on: bool) -> Result<(), Error>

Sets the value of the SO_BROADCAST option for this socket.

+

When enabled, this socket is allowed to send packets to a broadcast +address.

+

pub fn multicast_loop_v4(&self) -> Result<bool, Error>

Gets the value of the IP_MULTICAST_LOOP option for this socket.

+

For more information about this option, see set_multicast_loop_v4.

+

pub fn set_multicast_loop_v4(&self, on: bool) -> Result<(), Error>

Sets the value of the IP_MULTICAST_LOOP option for this socket.

+

If enabled, multicast packets will be looped back to the local socket.

+
§Note
+

This may not have any affect on IPv6 sockets.

+

pub fn multicast_ttl_v4(&self) -> Result<u32, Error>

Gets the value of the IP_MULTICAST_TTL option for this socket.

+

For more information about this option, see set_multicast_ttl_v4.

+

pub fn set_multicast_ttl_v4(&self, ttl: u32) -> Result<(), Error>

Sets the value of the IP_MULTICAST_TTL option for this socket.

+

Indicates the time-to-live value of outgoing multicast packets for +this socket. The default value is 1 which means that multicast packets +don’t leave the local network unless explicitly requested.

+
§Note
+

This may not have any affect on IPv6 sockets.

+

pub fn multicast_loop_v6(&self) -> Result<bool, Error>

Gets the value of the IPV6_MULTICAST_LOOP option for this socket.

+

For more information about this option, see set_multicast_loop_v6.

+

pub fn set_multicast_loop_v6(&self, on: bool) -> Result<(), Error>

Sets the value of the IPV6_MULTICAST_LOOP option for this socket.

+

Controls whether this socket sees the multicast packets it sends itself.

+
§Note
+

This may not have any affect on IPv4 sockets.

+

pub fn ttl(&self) -> Result<u32, Error>

Gets the value of the IP_TTL option for this socket.

+

For more information about this option, see set_ttl.

+
§Examples
+
use tokio::net::UdpSocket;
+
+let sock = UdpSocket::bind("127.0.0.1:8080").await?;
+
+println!("{:?}", sock.ttl()?);
+

pub fn set_ttl(&self, ttl: u32) -> Result<(), Error>

Sets the value for the IP_TTL option on this socket.

+

This value sets the time-to-live field that is used in every packet sent +from this socket.

+
§Examples
+
use tokio::net::UdpSocket;
+
+let sock = UdpSocket::bind("127.0.0.1:8080").await?;
+sock.set_ttl(60)?;
+
+

pub fn tos(&self) -> Result<u32, Error>

Gets the value of the IP_TOS option for this socket.

+

For more information about this option, see set_tos.

+

NOTE: On Windows, IP_TOS is only supported on Windows 8+ or +Windows Server 2012+.

+

pub fn set_tos(&self, tos: u32) -> Result<(), Error>

Sets the value for the IP_TOS option on this socket.

+

This value sets the type-of-service field that is used in every packet +sent from this socket.

+

NOTE: On Windows, IP_TOS is only supported on Windows 8+ or +Windows Server 2012+.

+

pub fn device(&self) -> Result<Option<Vec<u8>>, Error>

Gets the value for the SO_BINDTODEVICE option on this socket

+

This value gets the socket-bound device’s interface name.

+

pub fn bind_device(&self, interface: Option<&[u8]>) -> Result<(), Error>

Sets the value for the SO_BINDTODEVICE option on this socket

+

If a socket is bound to an interface, only packets received from that +particular interface are processed by the socket. Note that this only +works for some socket types, particularly AF_INET sockets.

+

If interface is None or an empty string it removes the binding.

+

pub fn join_multicast_v4( + &self, + multiaddr: Ipv4Addr, + interface: Ipv4Addr, +) -> Result<(), Error>

Executes an operation of the IP_ADD_MEMBERSHIP type.

+

This function specifies a new multicast group for this socket to join. +The address must be a valid multicast address, and interface is the +address of the local interface with which the system should join the +multicast group. If it’s equal to INADDR_ANY then an appropriate +interface is chosen by the system.

+

pub fn join_multicast_v6( + &self, + multiaddr: &Ipv6Addr, + interface: u32, +) -> Result<(), Error>

Executes an operation of the IPV6_ADD_MEMBERSHIP type.

+

This function specifies a new multicast group for this socket to join. +The address must be a valid multicast address, and interface is the +index of the interface to join/leave (or 0 to indicate any interface).

+

pub fn leave_multicast_v4( + &self, + multiaddr: Ipv4Addr, + interface: Ipv4Addr, +) -> Result<(), Error>

Executes an operation of the IP_DROP_MEMBERSHIP type.

+

For more information about this option, see join_multicast_v4.

+

pub fn leave_multicast_v6( + &self, + multiaddr: &Ipv6Addr, + interface: u32, +) -> Result<(), Error>

Executes an operation of the IPV6_DROP_MEMBERSHIP type.

+

For more information about this option, see join_multicast_v6.

+

pub fn take_error(&self) -> Result<Option<Error>, Error>

Returns the value of the SO_ERROR option.

+
§Examples
+
use tokio::net::UdpSocket;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Create a socket
+    let socket = UdpSocket::bind("0.0.0.0:8080").await?;
+
+    if let Ok(Some(err)) = socket.take_error() {
+        println!("Got error: {:?}", err);
+    }
+
+    Ok(())
+}
+

Trait Implementations§

§

impl AsFd for UdpSocket

§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
§

impl AsRawFd for UdpSocket

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl Debug for UdpSocket

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl TryFrom<UdpSocket> for UdpSocket

§

fn try_from( + stream: UdpSocket, +) -> Result<UdpSocket, <UdpSocket as TryFrom<UdpSocket>>::Error>

Consumes stream, returning the tokio I/O object.

+

This is equivalent to +UdpSocket::from_std(stream).

+
§

type Error = Error

The type returned in the event of a conversion error.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/net/struct.UnixDatagram.html b/actix_rt/net/struct.UnixDatagram.html new file mode 100644 index 00000000..465180b2 --- /dev/null +++ b/actix_rt/net/struct.UnixDatagram.html @@ -0,0 +1,868 @@ +UnixDatagram in actix_rt::net - Rust
actix_rt::net

Struct UnixDatagram

pub struct UnixDatagram { /* private fields */ }
Expand description

An I/O object representing a Unix datagram socket.

+

A socket can be either named (associated with a filesystem path) or +unnamed.

+

This type does not provide a split method, because this functionality +can be achieved by wrapping the socket in an Arc. Note that you do +not need a Mutex to share the UnixDatagram — an Arc<UnixDatagram> +is enough. This is because all of the methods take &self instead of +&mut self.

+

Note: named sockets are persisted even after the object is dropped +and the program has exited, and cannot be reconnected. It is advised +that you either check for and unlink the existing socket if it exists, +or use a temporary file that is guaranteed to not already exist.

+

§Examples

+

Using named sockets, associated with a filesystem path:

+ +
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// We use a temporary directory so that the socket
+// files left by the bound sockets will get cleaned up.
+let tmp = tempdir()?;
+
+// Bind each socket to a filesystem path
+let tx_path = tmp.path().join("tx");
+let tx = UnixDatagram::bind(&tx_path)?;
+let rx_path = tmp.path().join("rx");
+let rx = UnixDatagram::bind(&rx_path)?;
+
+let bytes = b"hello world";
+tx.send_to(bytes, &rx_path).await?;
+
+let mut buf = vec![0u8; 24];
+let (size, addr) = rx.recv_from(&mut buf).await?;
+
+let dgram = &buf[..size];
+assert_eq!(dgram, bytes);
+assert_eq!(addr.as_pathname().unwrap(), &tx_path);
+
+

Using unnamed sockets, created as a pair

+ +
use tokio::net::UnixDatagram;
+
+// Create the pair of sockets
+let (sock1, sock2) = UnixDatagram::pair()?;
+
+// Since the sockets are paired, the paired send/recv
+// functions can be used
+let bytes = b"hello world";
+sock1.send(bytes).await?;
+
+let mut buff = vec![0u8; 24];
+let size = sock2.recv(&mut buff).await?;
+
+let dgram = &buff[..size];
+assert_eq!(dgram, bytes);
+
+

Implementations§

§

impl UnixDatagram

pub async fn ready(&self, interest: Interest) -> Result<Ready, Error>

Waits for any of the requested ready states.

+

This function is usually paired with try_recv() or try_send(). It +can be used to concurrently recv / send to the same socket on a single +task without splitting the socket.

+

The function may complete without the socket being ready. This is a +false-positive and attempting an operation will return with +io::ErrorKind::WouldBlock. The function can also return with an empty +Ready set, so you should always check the returned value and possibly +wait again if the requested states are not set.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read or write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+

Concurrently receive from and send to the socket on the same task +without splitting.

+ +
use tokio::io::Interest;
+use tokio::net::UnixDatagram;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let dir = tempfile::tempdir().unwrap();
+    let client_path = dir.path().join("client.sock");
+    let server_path = dir.path().join("server.sock");
+    let socket = UnixDatagram::bind(&client_path)?;
+    socket.connect(&server_path)?;
+
+    loop {
+        let ready = socket.ready(Interest::READABLE | Interest::WRITABLE).await?;
+
+        if ready.is_readable() {
+            let mut data = [0; 1024];
+            match socket.try_recv(&mut data[..]) {
+                Ok(n) => {
+                    println!("received {:?}", &data[..n]);
+                }
+                // False-positive, continue
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
+                Err(e) => {
+                    return Err(e);
+                }
+            }
+        }
+
+        if ready.is_writable() {
+            // Write some data
+            match socket.try_send(b"hello world") {
+                Ok(n) => {
+                    println!("sent {} bytes", n);
+                }
+                // False-positive, continue
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
+                Err(e) => {
+                    return Err(e);
+                }
+            }
+        }
+    }
+}
+

pub async fn writable(&self) -> Result<(), Error>

Waits for the socket to become writable.

+

This function is equivalent to ready(Interest::WRITABLE) and is +usually paired with try_send() or try_send_to().

+

The function may complete without the socket being writable. This is a +false-positive and attempting a try_send() will return with +io::ErrorKind::WouldBlock.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let dir = tempfile::tempdir().unwrap();
+    let client_path = dir.path().join("client.sock");
+    let server_path = dir.path().join("server.sock");
+    let socket = UnixDatagram::bind(&client_path)?;
+    socket.connect(&server_path)?;
+
+    loop {
+        // Wait for the socket to be writable
+        socket.writable().await?;
+
+        // Try to send data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_send(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn poll_send_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for write/send readiness.

+

If the socket is not currently ready for sending, this method will +store a clone of the Waker from the provided Context. When the socket +becomes ready for sending, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_send_ready or poll_send, only +the Waker from the Context passed to the most recent call is +scheduled to receive a wakeup. (However, poll_recv_ready retains a +second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via writable is not feasible. Where possible, using writable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready for writing.
  • +
  • Poll::Ready(Ok(())) if the socket is ready for writing.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub async fn readable(&self) -> Result<(), Error>

Waits for the socket to become readable.

+

This function is equivalent to ready(Interest::READABLE) and is usually +paired with try_recv().

+

The function may complete without the socket being readable. This is a +false-positive and attempting a try_recv() will return with +io::ErrorKind::WouldBlock.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let client_path = dir.path().join("client.sock");
+    let server_path = dir.path().join("server.sock");
+    let socket = UnixDatagram::bind(&client_path)?;
+    socket.connect(&server_path)?;
+
+    loop {
+        // Wait for the socket to be readable
+        socket.readable().await?;
+
+        // The buffer is **not** included in the async task and will
+        // only exist on the stack.
+        let mut buf = [0; 1024];
+
+        // Try to recv data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_recv(&mut buf) {
+            Ok(n) => {
+                println!("GOT {:?}", &buf[..n]);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn poll_recv_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for read/receive readiness.

+

If the socket is not currently ready for receiving, this method will +store a clone of the Waker from the provided Context. When the +socket becomes ready for reading, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_recv_ready, poll_recv or +poll_peek, only the Waker from the Context passed to the most +recent call is scheduled to receive a wakeup. (However, +poll_send_ready retains a second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via readable is not feasible. Where possible, using readable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready for reading.
  • +
  • Poll::Ready(Ok(())) if the socket is ready for reading.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn bind<P>(path: P) -> Result<UnixDatagram, Error>
where + P: AsRef<Path>,

Creates a new UnixDatagram bound to the specified path.

+
§Examples
+
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// We use a temporary directory so that the socket
+// files left by the bound sockets will get cleaned up.
+let tmp = tempdir()?;
+
+// Bind the socket to a filesystem path
+let socket_path = tmp.path().join("socket");
+let socket = UnixDatagram::bind(&socket_path)?;
+
+

pub fn pair() -> Result<(UnixDatagram, UnixDatagram), Error>

Creates an unnamed pair of connected sockets.

+

This function will create a pair of interconnected Unix sockets for +communicating back and forth between one another.

+
§Examples
+
use tokio::net::UnixDatagram;
+
+// Create the pair of sockets
+let (sock1, sock2) = UnixDatagram::pair()?;
+
+// Since the sockets are paired, the paired send/recv
+// functions can be used
+let bytes = b"hail eris";
+sock1.send(bytes).await?;
+
+let mut buff = vec![0u8; 24];
+let size = sock2.recv(&mut buff).await?;
+
+let dgram = &buff[..size];
+assert_eq!(dgram, bytes);
+
+

pub fn from_std(datagram: UnixDatagram) -> Result<UnixDatagram, Error>

Creates new UnixDatagram from a std::os::unix::net::UnixDatagram.

+

This function is intended to be used to wrap a UnixDatagram from the +standard library in the Tokio equivalent.

+
§Notes
+

The caller is responsible for ensuring that the socket is in +non-blocking mode. Otherwise all I/O operations on the socket +will block the thread, which will cause unexpected behavior. +Non-blocking mode can be set using set_nonblocking.

+
§Panics
+

This function panics if it is not called from within a runtime with +IO enabled.

+

The runtime is usually set implicitly when this function is called +from a future driven by a Tokio runtime, otherwise runtime can be set +explicitly with Runtime::enter function.

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::os::unix::net::UnixDatagram as StdUDS;
+use tempfile::tempdir;
+
+// We use a temporary directory so that the socket
+// files left by the bound sockets will get cleaned up.
+let tmp = tempdir()?;
+
+// Bind the socket to a filesystem path
+let socket_path = tmp.path().join("socket");
+let std_socket = StdUDS::bind(&socket_path)?;
+std_socket.set_nonblocking(true)?;
+let tokio_socket = UnixDatagram::from_std(std_socket)?;
+
+

pub fn into_std(self) -> Result<UnixDatagram, Error>

Turns a tokio::net::UnixDatagram into a std::os::unix::net::UnixDatagram.

+

The returned std::os::unix::net::UnixDatagram will have nonblocking +mode set as true. Use set_nonblocking to change the blocking mode +if needed.

+
§Examples
+
let tokio_socket = tokio::net::UnixDatagram::bind("/path/to/the/socket")?;
+let std_socket = tokio_socket.into_std()?;
+std_socket.set_nonblocking(false)?;
+

pub fn unbound() -> Result<UnixDatagram, Error>

Creates a new UnixDatagram which is not bound to any address.

+
§Examples
+
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// Create an unbound socket
+let tx = UnixDatagram::unbound()?;
+
+// Create another, bound socket
+let tmp = tempdir()?;
+let rx_path = tmp.path().join("rx");
+let rx = UnixDatagram::bind(&rx_path)?;
+
+// Send to the bound socket
+let bytes = b"hello world";
+tx.send_to(bytes, &rx_path).await?;
+
+let mut buf = vec![0u8; 24];
+let (size, addr) = rx.recv_from(&mut buf).await?;
+
+let dgram = &buf[..size];
+assert_eq!(dgram, bytes);
+
+

pub fn connect<P>(&self, path: P) -> Result<(), Error>
where + P: AsRef<Path>,

Connects the socket to the specified address.

+

The send method may be used to send data to the specified address. +recv and recv_from will only receive data from that address.

+
§Examples
+
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// Create an unbound socket
+let tx = UnixDatagram::unbound()?;
+
+// Create another, bound socket
+let tmp = tempdir()?;
+let rx_path = tmp.path().join("rx");
+let rx = UnixDatagram::bind(&rx_path)?;
+
+// Connect to the bound socket
+tx.connect(&rx_path)?;
+
+// Send to the bound socket
+let bytes = b"hello world";
+tx.send(bytes).await?;
+
+let mut buf = vec![0u8; 24];
+let (size, addr) = rx.recv_from(&mut buf).await?;
+
+let dgram = &buf[..size];
+assert_eq!(dgram, bytes);
+
+

pub async fn send(&self, buf: &[u8]) -> Result<usize, Error>

Sends data on the socket to the socket’s peer.

+
§Cancel safety
+

This method is cancel safe. If send is used as the event in a +tokio::select! statement and some other branch +completes first, then it is guaranteed that the message was not sent.

+
§Examples
+
use tokio::net::UnixDatagram;
+
+// Create the pair of sockets
+let (sock1, sock2) = UnixDatagram::pair()?;
+
+// Since the sockets are paired, the paired send/recv
+// functions can be used
+let bytes = b"hello world";
+sock1.send(bytes).await?;
+
+let mut buff = vec![0u8; 24];
+let size = sock2.recv(&mut buff).await?;
+
+let dgram = &buff[..size];
+assert_eq!(dgram, bytes);
+
+

pub fn try_send(&self, buf: &[u8]) -> Result<usize, Error>

Tries to send a datagram to the peer without waiting.

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let dir = tempfile::tempdir().unwrap();
+    let client_path = dir.path().join("client.sock");
+    let server_path = dir.path().join("server.sock");
+    let socket = UnixDatagram::bind(&client_path)?;
+    socket.connect(&server_path)?;
+
+    loop {
+        // Wait for the socket to be writable
+        socket.writable().await?;
+
+        // Try to send data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_send(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_send_to<P>(&self, buf: &[u8], target: P) -> Result<usize, Error>
where + P: AsRef<Path>,

Tries to send a datagram to the peer without waiting.

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let dir = tempfile::tempdir().unwrap();
+    let client_path = dir.path().join("client.sock");
+    let server_path = dir.path().join("server.sock");
+    let socket = UnixDatagram::bind(&client_path)?;
+
+    loop {
+        // Wait for the socket to be writable
+        socket.writable().await?;
+
+        // Try to send data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_send_to(b"hello world", &server_path) {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub async fn recv(&self, buf: &mut [u8]) -> Result<usize, Error>

Receives data from the socket.

+
§Cancel safety
+

This method is cancel safe. If recv is used as the event in a +tokio::select! statement and some other branch +completes first, it is guaranteed that no messages were received on this +socket.

+
§Examples
+
use tokio::net::UnixDatagram;
+
+// Create the pair of sockets
+let (sock1, sock2) = UnixDatagram::pair()?;
+
+// Since the sockets are paired, the paired send/recv
+// functions can be used
+let bytes = b"hello world";
+sock1.send(bytes).await?;
+
+let mut buff = vec![0u8; 24];
+let size = sock2.recv(&mut buff).await?;
+
+let dgram = &buff[..size];
+assert_eq!(dgram, bytes);
+
+

pub fn try_recv(&self, buf: &mut [u8]) -> Result<usize, Error>

Tries to receive a datagram from the peer without waiting.

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let client_path = dir.path().join("client.sock");
+    let server_path = dir.path().join("server.sock");
+    let socket = UnixDatagram::bind(&client_path)?;
+    socket.connect(&server_path)?;
+
+    loop {
+        // Wait for the socket to be readable
+        socket.readable().await?;
+
+        // The buffer is **not** included in the async task and will
+        // only exist on the stack.
+        let mut buf = [0; 1024];
+
+        // Try to recv data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_recv(&mut buf) {
+            Ok(n) => {
+                println!("GOT {:?}", &buf[..n]);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub async fn send_to<P>(&self, buf: &[u8], target: P) -> Result<usize, Error>
where + P: AsRef<Path>,

Sends data on the socket to the specified address.

+
§Cancel safety
+

This method is cancel safe. If send_to is used as the event in a +tokio::select! statement and some other branch +completes first, then it is guaranteed that the message was not sent.

+
§Examples
+
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// We use a temporary directory so that the socket
+// files left by the bound sockets will get cleaned up.
+let tmp = tempdir()?;
+
+// Bind each socket to a filesystem path
+let tx_path = tmp.path().join("tx");
+let tx = UnixDatagram::bind(&tx_path)?;
+let rx_path = tmp.path().join("rx");
+let rx = UnixDatagram::bind(&rx_path)?;
+
+let bytes = b"hello world";
+tx.send_to(bytes, &rx_path).await?;
+
+let mut buf = vec![0u8; 24];
+let (size, addr) = rx.recv_from(&mut buf).await?;
+
+let dgram = &buf[..size];
+assert_eq!(dgram, bytes);
+assert_eq!(addr.as_pathname().unwrap(), &tx_path);
+
+

pub async fn recv_from( + &self, + buf: &mut [u8], +) -> Result<(usize, SocketAddr), Error>

Receives data from the socket.

+
§Cancel safety
+

This method is cancel safe. If recv_from is used as the event in a +tokio::select! statement and some other branch +completes first, it is guaranteed that no messages were received on this +socket.

+
§Examples
+
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// We use a temporary directory so that the socket
+// files left by the bound sockets will get cleaned up.
+let tmp = tempdir()?;
+
+// Bind each socket to a filesystem path
+let tx_path = tmp.path().join("tx");
+let tx = UnixDatagram::bind(&tx_path)?;
+let rx_path = tmp.path().join("rx");
+let rx = UnixDatagram::bind(&rx_path)?;
+
+let bytes = b"hello world";
+tx.send_to(bytes, &rx_path).await?;
+
+let mut buf = vec![0u8; 24];
+let (size, addr) = rx.recv_from(&mut buf).await?;
+
+let dgram = &buf[..size];
+assert_eq!(dgram, bytes);
+assert_eq!(addr.as_pathname().unwrap(), &tx_path);
+
+

pub fn poll_recv_from( + &self, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<SocketAddr, Error>>

Attempts to receive a single datagram on the specified address.

+

Note that on multiple calls to a poll_* method in the recv direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready to read
  • +
  • Poll::Ready(Ok(addr)) reads data from addr into ReadBuf if the socket is ready
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn poll_send_to<P>( + &self, + cx: &mut Context<'_>, + buf: &[u8], + target: P, +) -> Poll<Result<usize, Error>>
where + P: AsRef<Path>,

Attempts to send data to the specified address.

+

Note that on multiple calls to a poll_* method in the send direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready to write
  • +
  • Poll::Ready(Ok(n)) n is the number of bytes sent.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn poll_send( + &self, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Attempts to send data on the socket to the remote address to which it +was previously connected.

+

The connect method will connect this socket to a remote address. +This method will fail if the socket is not connected.

+

Note that on multiple calls to a poll_* method in the send direction, +only the Waker from the Context passed to the most recent call will +be scheduled to receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not available to write
  • +
  • Poll::Ready(Ok(n)) n is the number of bytes sent
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn poll_recv( + &self, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to receive a single datagram message on the socket from the remote +address to which it is connected.

+

The connect method will connect this socket to a remote address. This method +resolves to an error if the socket is not connected.

+

Note that on multiple calls to a poll_* method in the recv direction, only the +Waker from the Context passed to the most recent call will be scheduled to +receive a wakeup.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the socket is not ready to read
  • +
  • Poll::Ready(Ok(())) reads data ReadBuf if the socket is ready
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_recv_from( + &self, + buf: &mut [u8], +) -> Result<(usize, SocketAddr), Error>

Tries to receive data from the socket without waiting.

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let client_path = dir.path().join("client.sock");
+    let server_path = dir.path().join("server.sock");
+    let socket = UnixDatagram::bind(&client_path)?;
+
+    loop {
+        // Wait for the socket to be readable
+        socket.readable().await?;
+
+        // The buffer is **not** included in the async task and will
+        // only exist on the stack.
+        let mut buf = [0; 1024];
+
+        // Try to recv data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match socket.try_recv_from(&mut buf) {
+            Ok((n, _addr)) => {
+                println!("GOT {:?}", &buf[..n]);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e);
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_io<R>( + &self, + interest: Interest, + f: impl FnOnce() -> Result<R, Error>, +) -> Result<R, Error>

Tries to read or write from the socket using a user-provided IO operation.

+

If the socket is ready, the provided closure is called. The closure +should attempt to perform IO operation on the socket by manually +calling the appropriate syscall. If the operation fails because the +socket is not actually ready, then the closure should return a +WouldBlock error and the readiness flag is cleared. The return value +of the closure is then returned by try_io.

+

If the socket is not ready, then the closure is not called +and a WouldBlock error is returned.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio UnixDatagram type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

Usually, readable(), writable() or ready() is used with this function.

+

pub async fn async_io<R>( + &self, + interest: Interest, + f: impl FnMut() -> Result<R, Error>, +) -> Result<R, Error>

Reads or writes from the socket using a user-provided IO operation.

+

The readiness of the socket is awaited and when the socket is ready, +the provided closure is called. The closure should attempt to perform +IO operation on the socket by manually calling the appropriate syscall. +If the operation fails because the socket is not actually ready, +then the closure should return a WouldBlock error. In such case the +readiness flag is cleared and the socket readiness is awaited again. +This loop is repeated until the closure returns an Ok or an error +other than WouldBlock.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio UnixDatagram type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

pub fn local_addr(&self) -> Result<SocketAddr, Error>

Returns the local address that this socket is bound to.

+
§Examples
+

For a socket bound to a local path

+ +
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// We use a temporary directory so that the socket
+// files left by the bound sockets will get cleaned up.
+let tmp = tempdir()?;
+
+// Bind socket to a filesystem path
+let socket_path = tmp.path().join("socket");
+let socket = UnixDatagram::bind(&socket_path)?;
+
+assert_eq!(socket.local_addr()?.as_pathname().unwrap(), &socket_path);
+
+

For an unbound socket

+ +
use tokio::net::UnixDatagram;
+
+// Create an unbound socket
+let socket = UnixDatagram::unbound()?;
+
+assert!(socket.local_addr()?.is_unnamed());
+
+

pub fn peer_addr(&self) -> Result<SocketAddr, Error>

Returns the address of this socket’s peer.

+

The connect method will connect the socket to a peer.

+
§Examples
+

For a peer with a local path

+ +
use tokio::net::UnixDatagram;
+use tempfile::tempdir;
+
+// Create an unbound socket
+let tx = UnixDatagram::unbound()?;
+
+// Create another, bound socket
+let tmp = tempdir()?;
+let rx_path = tmp.path().join("rx");
+let rx = UnixDatagram::bind(&rx_path)?;
+
+// Connect to the bound socket
+tx.connect(&rx_path)?;
+
+assert_eq!(tx.peer_addr()?.as_pathname().unwrap(), &rx_path);
+
+

For an unbound peer

+ +
use tokio::net::UnixDatagram;
+
+// Create the pair of sockets
+let (sock1, sock2) = UnixDatagram::pair()?;
+
+assert!(sock1.peer_addr()?.is_unnamed());
+
+

pub fn take_error(&self) -> Result<Option<Error>, Error>

Returns the value of the SO_ERROR option.

+
§Examples
+
use tokio::net::UnixDatagram;
+
+// Create an unbound socket
+let socket = UnixDatagram::unbound()?;
+
+if let Ok(Some(err)) = socket.take_error() {
+    println!("Got error: {:?}", err);
+}
+
+

pub fn shutdown(&self, how: Shutdown) -> Result<(), Error>

Shuts down the read, write, or both halves of this connection.

+

This function will cause all pending and future I/O calls on the +specified portions to immediately return with an appropriate value +(see the documentation of Shutdown).

+
§Examples
+
use tokio::net::UnixDatagram;
+use std::net::Shutdown;
+
+// Create an unbound socket
+let (socket, other) = UnixDatagram::pair()?;
+
+socket.shutdown(Shutdown::Both)?;
+
+// NOTE: the following commented out code does NOT work as expected.
+// Due to an underlying issue, the recv call will block indefinitely.
+// See: https://github.com/tokio-rs/tokio/issues/1679
+//let mut buff = vec![0u8; 24];
+//let size = socket.recv(&mut buff).await?;
+//assert_eq!(size, 0);
+
+let send_result = socket.send(b"hello world").await;
+assert!(send_result.is_err());
+
+

Trait Implementations§

§

impl AsFd for UnixDatagram

§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
§

impl AsRawFd for UnixDatagram

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl Debug for UnixDatagram

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl TryFrom<UnixDatagram> for UnixDatagram

§

fn try_from( + stream: UnixDatagram, +) -> Result<UnixDatagram, <UnixDatagram as TryFrom<UnixDatagram>>::Error>

Consumes stream, returning the Tokio I/O object.

+

This is equivalent to +UnixDatagram::from_std(stream).

+
§

type Error = Error

The type returned in the event of a conversion error.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/net/struct.UnixListener.html b/actix_rt/net/struct.UnixListener.html new file mode 100644 index 00000000..6fd738ba --- /dev/null +++ b/actix_rt/net/struct.UnixListener.html @@ -0,0 +1,90 @@ +UnixListener in actix_rt::net - Rust
actix_rt::net

Struct UnixListener

pub struct UnixListener { /* private fields */ }
Expand description

A Unix socket which can accept connections from other Unix sockets.

+

You can accept a new connection by using the accept method.

+

A UnixListener can be turned into a Stream with UnixListenerStream.

+

§Errors

+

Note that accepting a connection can lead to various errors and not all +of them are necessarily fatal ‒ for example having too many open file +descriptors or the other side closing the connection while it waits in +an accept queue. These would terminate the stream if not handled in any +way.

+

§Examples

+
use tokio::net::UnixListener;
+
+#[tokio::main]
+async fn main() {
+    let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    loop {
+        match listener.accept().await {
+            Ok((stream, _addr)) => {
+                println!("new client!");
+            }
+            Err(e) => { /* connection failed */ }
+        }
+    }
+}
+

Implementations§

§

impl UnixListener

pub fn bind<P>(path: P) -> Result<UnixListener, Error>
where + P: AsRef<Path>,

Creates a new UnixListener bound to the specified path.

+
§Panics
+

This function panics if it is not called from within a runtime with +IO enabled.

+

The runtime is usually set implicitly when this function is called +from a future driven by a tokio runtime, otherwise runtime can be set +explicitly with Runtime::enter function.

+

pub fn from_std(listener: UnixListener) -> Result<UnixListener, Error>

Creates new UnixListener from a std::os::unix::net::UnixListener.

+

This function is intended to be used to wrap a UnixListener from the +standard library in the Tokio equivalent.

+
§Notes
+

The caller is responsible for ensuring that the listener is in +non-blocking mode. Otherwise all I/O operations on the listener +will block the thread, which will cause unexpected behavior. +Non-blocking mode can be set using set_nonblocking.

+
§Examples
+
use tokio::net::UnixListener;
+use std::os::unix::net::UnixListener as StdUnixListener;
+
+let std_listener = StdUnixListener::bind("/path/to/the/socket")?;
+std_listener.set_nonblocking(true)?;
+let listener = UnixListener::from_std(std_listener)?;
+
§Panics
+

This function panics if it is not called from within a runtime with +IO enabled.

+

The runtime is usually set implicitly when this function is called +from a future driven by a tokio runtime, otherwise runtime can be set +explicitly with Runtime::enter function.

+

pub fn into_std(self) -> Result<UnixListener, Error>

Turns a tokio::net::UnixListener into a std::os::unix::net::UnixListener.

+

The returned std::os::unix::net::UnixListener will have nonblocking mode +set as true. Use set_nonblocking to change the blocking mode if needed.

+
§Examples
+
let tokio_listener = tokio::net::UnixListener::bind("/path/to/the/socket")?;
+let std_listener = tokio_listener.into_std()?;
+std_listener.set_nonblocking(false)?;
+

pub fn local_addr(&self) -> Result<SocketAddr, Error>

Returns the local socket address of this listener.

+

pub fn take_error(&self) -> Result<Option<Error>, Error>

Returns the value of the SO_ERROR option.

+

pub async fn accept(&self) -> Result<(UnixStream, SocketAddr), Error>

Accepts a new incoming connection to this listener.

+
§Cancel safety
+

This method is cancel safe. If the method is used as the event in a +tokio::select! statement and some other branch +completes first, then it is guaranteed that no new connections were +accepted by this method.

+

pub fn poll_accept( + &self, + cx: &mut Context<'_>, +) -> Poll<Result<(UnixStream, SocketAddr), Error>>

Polls to accept a new incoming connection to this listener.

+

If there is no connection to accept, Poll::Pending is returned and the +current task will be notified by a waker. Note that on multiple calls +to poll_accept, only the Waker from the Context passed to the most +recent call is scheduled to receive a wakeup.

+

Trait Implementations§

§

impl AsFd for UnixListener

§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
§

impl AsRawFd for UnixListener

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl Debug for UnixListener

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl TryFrom<UnixListener> for UnixListener

§

fn try_from(stream: UnixListener) -> Result<UnixListener, Error>

Consumes stream, returning the tokio I/O object.

+

This is equivalent to +UnixListener::from_std(stream).

+
§

type Error = Error

The type returned in the event of a conversion error.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/net/struct.UnixStream.html b/actix_rt/net/struct.UnixStream.html new file mode 100644 index 00000000..a4636b3a --- /dev/null +++ b/actix_rt/net/struct.UnixStream.html @@ -0,0 +1,575 @@ +UnixStream in actix_rt::net - Rust
actix_rt::net

Struct UnixStream

pub struct UnixStream { /* private fields */ }
Expand description

A structure representing a connected Unix socket.

+

This socket can be connected directly with UnixStream::connect or accepted +from a listener with UnixListener::accept. Additionally, a pair of +anonymous Unix sockets can be created with UnixStream::pair.

+

To shut down the stream in the write direction, you can call the +shutdown() method. This will cause the other peer to receive a read of +length 0, indicating that no more data will be sent. This only closes +the stream in one direction.

+

Implementations§

§

impl UnixStream

pub async fn connect<P>(path: P) -> Result<UnixStream, Error>
where + P: AsRef<Path>,

Connects to the socket named by path.

+

This function will create a new Unix socket and connect to the path +specified, associating the returned stream with the default event loop’s +handle.

+

pub async fn ready(&self, interest: Interest) -> Result<Ready, Error>

Waits for any of the requested ready states.

+

This function is usually paired with try_read() or try_write(). It +can be used to concurrently read / write to the same socket on a single +task without splitting the socket.

+

The function may complete without the socket being ready. This is a +false-positive and attempting an operation will return with +io::ErrorKind::WouldBlock. The function can also return with an empty +Ready set, so you should always check the returned value and possibly +wait again if the requested states are not set.

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read or write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+

Concurrently read and write to the stream on the same task without +splitting.

+ +
use tokio::io::Interest;
+use tokio::net::UnixStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+    let stream = UnixStream::connect(bind_path).await?;
+
+    loop {
+        let ready = stream.ready(Interest::READABLE | Interest::WRITABLE).await?;
+
+        if ready.is_readable() {
+            let mut data = vec![0; 1024];
+            // Try to read data, this may still fail with `WouldBlock`
+            // if the readiness event is a false positive.
+            match stream.try_read(&mut data) {
+                Ok(n) => {
+                    println!("read {} bytes", n);        
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                    continue;
+                }
+                Err(e) => {
+                    return Err(e.into());
+                }
+            }
+
+        }
+
+        if ready.is_writable() {
+            // Try to write data, this may still fail with `WouldBlock`
+            // if the readiness event is a false positive.
+            match stream.try_write(b"hello world") {
+                Ok(n) => {
+                    println!("write {} bytes", n);
+                }
+                Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                    continue;
+                }
+                Err(e) => {
+                    return Err(e.into());
+                }
+            }
+        }
+    }
+}
+

pub async fn readable(&self) -> Result<(), Error>

Waits for the socket to become readable.

+

This function is equivalent to ready(Interest::READABLE) and is usually +paired with try_read().

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to read that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::UnixStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+    let stream = UnixStream::connect(bind_path).await?;
+
+    let mut msg = vec![0; 1024];
+
+    loop {
+        // Wait for the socket to be readable
+        stream.readable().await?;
+
+        // Try to read data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_read(&mut msg) {
+            Ok(n) => {
+                msg.truncate(n);
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    println!("GOT = {:?}", msg);
+    Ok(())
+}
+

pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for read readiness.

+

If the unix stream is not currently ready for reading, this method will +store a clone of the Waker from the provided Context. When the unix +stream becomes ready for reading, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_read_ready or poll_read, only +the Waker from the Context passed to the most recent call is +scheduled to receive a wakeup. (However, poll_write_ready retains a +second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via readable is not feasible. Where possible, using readable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the unix stream is not ready for reading.
  • +
  • Poll::Ready(Ok(())) if the unix stream is ready for reading.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_read(&self, buf: &mut [u8]) -> Result<usize, Error>

Try to read data from the stream into the provided buffer, returning how +many bytes were read.

+

Receives any pending data from the socket but does not wait for new data +to arrive. On success, returns the number of bytes read. Because +try_read() is non-blocking, the buffer does not have to be stored by +the async task and can exist entirely on the stack.

+

Usually, readable() or ready() is used with this function.

+
§Return
+

If data is successfully read, Ok(n) is returned, where n is the +number of bytes read. If n is 0, then it can indicate one of two scenarios:

+
    +
  1. The stream’s read half is closed and will no longer yield data.
  2. +
  3. The specified buffer was 0 bytes in length.
  4. +
+

If the stream is not ready to read data, +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::UnixStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+    let stream = UnixStream::connect(bind_path).await?;
+
+    loop {
+        // Wait for the socket to be readable
+        stream.readable().await?;
+
+        // Creating the buffer **after** the `await` prevents it from
+        // being stored in the async task.
+        let mut buf = [0; 4096];
+
+        // Try to read data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_read(&mut buf) {
+            Ok(0) => break,
+            Ok(n) => {
+                println!("read {} bytes", n);
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_read_vectored( + &self, + bufs: &mut [IoSliceMut<'_>], +) -> Result<usize, Error>

Tries to read data from the stream into the provided buffers, returning +how many bytes were read.

+

Data is copied to fill each buffer in order, with the final buffer +written to possibly being only partially filled. This method behaves +equivalently to a single call to try_read() with concatenated +buffers.

+

Receives any pending data from the socket but does not wait for new data +to arrive. On success, returns the number of bytes read. Because +try_read_vectored() is non-blocking, the buffer does not have to be +stored by the async task and can exist entirely on the stack.

+

Usually, readable() or ready() is used with this function.

+
§Return
+

If data is successfully read, Ok(n) is returned, where n is the +number of bytes read. Ok(0) indicates the stream’s read half is closed +and will no longer yield data. If the stream is not ready to read data +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::UnixStream;
+use std::error::Error;
+use std::io::{self, IoSliceMut};
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+    let stream = UnixStream::connect(bind_path).await?;
+
+    loop {
+        // Wait for the socket to be readable
+        stream.readable().await?;
+
+        // Creating the buffer **after** the `await` prevents it from
+        // being stored in the async task.
+        let mut buf_a = [0; 512];
+        let mut buf_b = [0; 1024];
+        let mut bufs = [
+            IoSliceMut::new(&mut buf_a),
+            IoSliceMut::new(&mut buf_b),
+        ];
+
+        // Try to read data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_read_vectored(&mut bufs) {
+            Ok(0) => break,
+            Ok(n) => {
+                println!("read {} bytes", n);
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub async fn writable(&self) -> Result<(), Error>

Waits for the socket to become writable.

+

This function is equivalent to ready(Interest::WRITABLE) and is usually +paired with try_write().

+
§Cancel safety
+

This method is cancel safe. Once a readiness event occurs, the method +will continue to return immediately until the readiness event is +consumed by an attempt to write that fails with WouldBlock or +Poll::Pending.

+
§Examples
+
use tokio::net::UnixStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+    let stream = UnixStream::connect(bind_path).await?;
+
+    loop {
+        // Wait for the socket to be writable
+        stream.writable().await?;
+
+        // Try to write data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_write(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>>

Polls for write readiness.

+

If the unix stream is not currently ready for writing, this method will +store a clone of the Waker from the provided Context. When the unix +stream becomes ready for writing, Waker::wake will be called on the +waker.

+

Note that on multiple calls to poll_write_ready or poll_write, only +the Waker from the Context passed to the most recent call is +scheduled to receive a wakeup. (However, poll_read_ready retains a +second, independent waker.)

+

This function is intended for cases where creating and pinning a future +via writable is not feasible. Where possible, using writable is +preferred, as this supports polling from multiple tasks at once.

+
§Return value
+

The function returns:

+
    +
  • Poll::Pending if the unix stream is not ready for writing.
  • +
  • Poll::Ready(Ok(())) if the unix stream is ready for writing.
  • +
  • Poll::Ready(Err(e)) if an error is encountered.
  • +
+
§Errors
+

This function may encounter any standard I/O error except WouldBlock.

+

pub fn try_write(&self, buf: &[u8]) -> Result<usize, Error>

Tries to write a buffer to the stream, returning how many bytes were +written.

+

The function will attempt to write the entire contents of buf, but +only part of the buffer may be written.

+

This function is usually paired with writable().

+
§Return
+

If data is successfully written, Ok(n) is returned, where n is the +number of bytes written. If the stream is not ready to write data, +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::UnixStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+    let stream = UnixStream::connect(bind_path).await?;
+
+    loop {
+        // Wait for the socket to be writable
+        stream.writable().await?;
+
+        // Try to write data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_write(b"hello world") {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_write_vectored(&self, buf: &[IoSlice<'_>]) -> Result<usize, Error>

Tries to write several buffers to the stream, returning how many bytes +were written.

+

Data is written from each buffer in order, with the final buffer read +from possible being only partially consumed. This method behaves +equivalently to a single call to try_write() with concatenated +buffers.

+

This function is usually paired with writable().

+
§Return
+

If data is successfully written, Ok(n) is returned, where n is the +number of bytes written. If the stream is not ready to write data, +Err(io::ErrorKind::WouldBlock) is returned.

+
§Examples
+
use tokio::net::UnixStream;
+use std::error::Error;
+use std::io;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    // Connect to a peer
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+    let stream = UnixStream::connect(bind_path).await?;
+
+    let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")];
+
+    loop {
+        // Wait for the socket to be writable
+        stream.writable().await?;
+
+        // Try to write data, this may still fail with `WouldBlock`
+        // if the readiness event is a false positive.
+        match stream.try_write_vectored(&bufs) {
+            Ok(n) => {
+                break;
+            }
+            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
+                continue;
+            }
+            Err(e) => {
+                return Err(e.into());
+            }
+        }
+    }
+
+    Ok(())
+}
+

pub fn try_io<R>( + &self, + interest: Interest, + f: impl FnOnce() -> Result<R, Error>, +) -> Result<R, Error>

Tries to read or write from the socket using a user-provided IO operation.

+

If the socket is ready, the provided closure is called. The closure +should attempt to perform IO operation on the socket by manually +calling the appropriate syscall. If the operation fails because the +socket is not actually ready, then the closure should return a +WouldBlock error and the readiness flag is cleared. The return value +of the closure is then returned by try_io.

+

If the socket is not ready, then the closure is not called +and a WouldBlock error is returned.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio UnixStream type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

Usually, readable(), writable() or ready() is used with this function.

+

pub async fn async_io<R>( + &self, + interest: Interest, + f: impl FnMut() -> Result<R, Error>, +) -> Result<R, Error>

Reads or writes from the socket using a user-provided IO operation.

+

The readiness of the socket is awaited and when the socket is ready, +the provided closure is called. The closure should attempt to perform +IO operation on the socket by manually calling the appropriate syscall. +If the operation fails because the socket is not actually ready, +then the closure should return a WouldBlock error. In such case the +readiness flag is cleared and the socket readiness is awaited again. +This loop is repeated until the closure returns an Ok or an error +other than WouldBlock.

+

The closure should only return a WouldBlock error if it has performed +an IO operation on the socket that failed due to the socket not being +ready. Returning a WouldBlock error in any other situation will +incorrectly clear the readiness flag, which can cause the socket to +behave incorrectly.

+

The closure should not perform the IO operation using any of the methods +defined on the Tokio UnixStream type, as this will mess with the +readiness flag and can cause the socket to behave incorrectly.

+

This method is not intended to be used with combined interests. +The closure should perform only one type of IO operation, so it should not +require more than one ready state. This method may panic or sleep forever +if it is called with a combined interest.

+

pub fn from_std(stream: UnixStream) -> Result<UnixStream, Error>

Creates new UnixStream from a std::os::unix::net::UnixStream.

+

This function is intended to be used to wrap a UnixStream from the +standard library in the Tokio equivalent.

+
§Notes
+

The caller is responsible for ensuring that the stream is in +non-blocking mode. Otherwise all I/O operations on the stream +will block the thread, which will cause unexpected behavior. +Non-blocking mode can be set using set_nonblocking.

+
§Examples
+
use tokio::net::UnixStream;
+use std::os::unix::net::UnixStream as StdUnixStream;
+
+let std_stream = StdUnixStream::connect("/path/to/the/socket")?;
+std_stream.set_nonblocking(true)?;
+let stream = UnixStream::from_std(std_stream)?;
+
§Panics
+

This function panics if it is not called from within a runtime with +IO enabled.

+

The runtime is usually set implicitly when this function is called +from a future driven by a tokio runtime, otherwise runtime can be set +explicitly with Runtime::enter function.

+

pub fn into_std(self) -> Result<UnixStream, Error>

Turns a tokio::net::UnixStream into a std::os::unix::net::UnixStream.

+

The returned std::os::unix::net::UnixStream will have nonblocking +mode set as true. Use set_nonblocking to change the blocking +mode if needed.

+
§Examples
+
use std::error::Error;
+use std::io::Read;
+use tokio::net::UnixListener;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let dir = tempfile::tempdir().unwrap();
+    let bind_path = dir.path().join("bind_path");
+
+    let mut data = [0u8; 12];
+    let listener = UnixListener::bind(&bind_path)?;
+    let (tokio_unix_stream, _) = listener.accept().await?;
+    let mut std_unix_stream = tokio_unix_stream.into_std()?;
+    std_unix_stream.set_nonblocking(false)?;
+    std_unix_stream.read_exact(&mut data)?;
+    Ok(())
+}
+

pub fn pair() -> Result<(UnixStream, UnixStream), Error>

Creates an unnamed pair of connected sockets.

+

This function will create a pair of interconnected Unix sockets for +communicating back and forth between one another. Each socket will +be associated with the default event loop’s handle.

+

pub fn local_addr(&self) -> Result<SocketAddr, Error>

Returns the socket address of the local half of this connection.

+
§Examples
+
use tokio::net::UnixStream;
+
+let dir = tempfile::tempdir().unwrap();
+let bind_path = dir.path().join("bind_path");
+let stream = UnixStream::connect(bind_path).await?;
+
+println!("{:?}", stream.local_addr()?);
+

pub fn peer_addr(&self) -> Result<SocketAddr, Error>

Returns the socket address of the remote half of this connection.

+
§Examples
+
use tokio::net::UnixStream;
+
+let dir = tempfile::tempdir().unwrap();
+let bind_path = dir.path().join("bind_path");
+let stream = UnixStream::connect(bind_path).await?;
+
+println!("{:?}", stream.peer_addr()?);
+

pub fn peer_cred(&self) -> Result<UCred, Error>

Returns effective credentials of the process which called connect or pair.

+

pub fn take_error(&self) -> Result<Option<Error>, Error>

Returns the value of the SO_ERROR option.

+

pub fn split<'a>(&'a mut self) -> (ReadHalf<'a>, WriteHalf<'a>)

Splits a UnixStream into a read half and a write half, which can be used +to read and write the stream concurrently.

+

This method is more efficient than into_split, but the halves cannot be +moved into independently spawned tasks.

+

pub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf)

Splits a UnixStream into a read half and a write half, which can be used +to read and write the stream concurrently.

+

Unlike split, the owned halves can be moved to separate tasks, however +this comes at the cost of a heap allocation.

+

Note: Dropping the write half will shut down the write half of the +stream. This is equivalent to calling shutdown() on the UnixStream.

+

Trait Implementations§

§

impl AsFd for UnixStream

§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
§

impl AsRawFd for UnixStream

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl AsyncRead for UnixStream

§

fn poll_read( + self: Pin<&mut UnixStream>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
§

impl AsyncWrite for UnixStream

§

fn poll_write( + self: Pin<&mut UnixStream>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Attempt to write bytes from buf into the object. Read more
§

fn poll_write_vectored( + self: Pin<&mut UnixStream>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
§

fn poll_flush( + self: Pin<&mut UnixStream>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
§

fn poll_shutdown( + self: Pin<&mut UnixStream>, + _: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

impl Debug for UnixStream

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl TryFrom<UnixStream> for UnixStream

§

fn try_from(stream: UnixStream) -> Result<UnixStream, Error>

Consumes stream, returning the tokio I/O object.

+

This is equivalent to +UnixStream::from_std(stream).

+
§

type Error = Error

The type returned in the event of a conversion error.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/runtime/struct.Runtime.html b/actix_rt/runtime/struct.Runtime.html new file mode 100644 index 00000000..3c64fec5 --- /dev/null +++ b/actix_rt/runtime/struct.Runtime.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_rt/struct.Runtime.html...

+ + + \ No newline at end of file diff --git a/actix_rt/sidebar-items.js b/actix_rt/sidebar-items.js new file mode 100644 index 00000000..5909e6a6 --- /dev/null +++ b/actix_rt/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"attr":["main","test"],"fn":["spawn"],"macro":["pin"],"mod":["net","signal","task","time"],"struct":["Arbiter","ArbiterHandle","Runtime","System","SystemRunner"]}; \ No newline at end of file diff --git a/actix_rt/signal/fn.ctrl_c.html b/actix_rt/signal/fn.ctrl_c.html new file mode 100644 index 00000000..f71986ab --- /dev/null +++ b/actix_rt/signal/fn.ctrl_c.html @@ -0,0 +1,39 @@ +ctrl_c in actix_rt::signal - Rust
actix_rt::signal

Function ctrl_c

pub async fn ctrl_c() -> Result<(), Error>
Expand description

Completes when a “ctrl-c” notification is sent to the process.

+

While signals are handled very differently between Unix and Windows, both +platforms support receiving a signal on “ctrl-c”. This function provides a +portable API for receiving this notification.

+

Once the returned future is polled, a listener is registered. The future +will complete on the first received ctrl-c after the initial call to +either Future::poll or .await.

+

§Caveats

+

On Unix platforms, the first time that a Signal instance is registered for a +particular signal kind, an OS signal-handler is installed which replaces the +default platform behavior when that signal is received, for the duration of +the entire process.

+

For example, Unix systems will terminate a process by default when it +receives a signal generated by "CTRL+C" on the terminal. But, when a +ctrl_c stream is created to listen for this signal, the time it arrives, +it will be translated to a stream event, and the process will continue to +execute. Even if this Signal instance is dropped, subsequent SIGINT +deliveries will end up captured by Tokio, and the default platform behavior +will NOT be reset.

+

Thus, applications should take care to ensure the expected signal behavior +occurs as expected after listening for specific signals.

+

§Examples

+
use tokio::signal;
+
+#[tokio::main]
+async fn main() {
+    println!("waiting for ctrl-c");
+
+    signal::ctrl_c().await.expect("failed to listen for event");
+
+    println!("received ctrl-c event");
+}
+

Listen in the background:

+ +
tokio::spawn(async move {
+    tokio::signal::ctrl_c().await.unwrap();
+    // Your handler here
+});
+
\ No newline at end of file diff --git a/actix_rt/signal/index.html b/actix_rt/signal/index.html new file mode 100644 index 00000000..5328388a --- /dev/null +++ b/actix_rt/signal/index.html @@ -0,0 +1,2 @@ +actix_rt::signal - Rust
actix_rt

Module signal

source
Expand description

Asynchronous signal handling (Tokio re-exports).

+

Modules§

  • Unix specific signals (Tokio re-exports).

Functions§

  • Completes when a “ctrl-c” notification is sent to the process.
\ No newline at end of file diff --git a/actix_rt/signal/sidebar-items.js b/actix_rt/signal/sidebar-items.js new file mode 100644 index 00000000..ad5573ca --- /dev/null +++ b/actix_rt/signal/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["ctrl_c"],"mod":["unix"]}; \ No newline at end of file diff --git a/actix_rt/signal/unix/fn.signal.html b/actix_rt/signal/unix/fn.signal.html new file mode 100644 index 00000000..e9e69136 --- /dev/null +++ b/actix_rt/signal/unix/fn.signal.html @@ -0,0 +1,25 @@ +signal in actix_rt::signal::unix - Rust
actix_rt::signal::unix

Function signal

pub fn signal(kind: SignalKind) -> Result<Signal, Error>
Expand description

Creates a new listener which will receive notifications when the current +process receives the specified signal kind.

+

This function will create a new stream which binds to the default reactor. +The Signal stream is an infinite stream which will receive +notifications whenever a signal is received. More documentation can be +found on Signal itself, but to reiterate:

+
    +
  • Signals may be coalesced beyond what the kernel already does.
  • +
  • Once a signal handler is registered with the process the underlying +libc signal handler is never unregistered.
  • +
+

A Signal stream can be created for a particular signal number +multiple times. When a signal is received then all the associated +channels will receive the signal notification.

+

§Errors

+
    +
  • If the lower-level C functions fail for some reason.
  • +
  • If the previous initialization of this specific signal failed.
  • +
  • If the signal is one of +signal_hook::FORBIDDEN
  • +
+

§Panics

+

This function panics if there is no current reactor set, or if the rt +feature flag is not enabled.

+
\ No newline at end of file diff --git a/actix_rt/signal/unix/index.html b/actix_rt/signal/unix/index.html new file mode 100644 index 00000000..4880da47 --- /dev/null +++ b/actix_rt/signal/unix/index.html @@ -0,0 +1,3 @@ +actix_rt::signal::unix - Rust
actix_rt::signal

Module unix

source
Expand description

Unix specific signals (Tokio re-exports).

+

Structs§

  • An listener for receiving a particular type of OS signal.
  • Represents the specific kind of signal to listen for.

Functions§

  • Creates a new listener which will receive notifications when the current +process receives the specified signal kind.
\ No newline at end of file diff --git a/actix_rt/signal/unix/sidebar-items.js b/actix_rt/signal/unix/sidebar-items.js new file mode 100644 index 00000000..344a2272 --- /dev/null +++ b/actix_rt/signal/unix/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["signal"],"struct":["Signal","SignalKind"]}; \ No newline at end of file diff --git a/actix_rt/signal/unix/struct.Signal.html b/actix_rt/signal/unix/struct.Signal.html new file mode 100644 index 00000000..ac20aa0e --- /dev/null +++ b/actix_rt/signal/unix/struct.Signal.html @@ -0,0 +1,119 @@ +Signal in actix_rt::signal::unix - Rust
actix_rt::signal::unix

Struct Signal

pub struct Signal { /* private fields */ }
Expand description

An listener for receiving a particular type of OS signal.

+

The listener can be turned into a Stream using SignalStream.

+

In general signal handling on Unix is a pretty tricky topic, and this +structure is no exception! There are some important limitations to keep in +mind when using Signal streams:

+
    +
  • +

    Signals handling in Unix already necessitates coalescing signals +together sometimes. This Signal stream is also no exception here in +that it will also coalesce signals. That is, even if the signal handler +for this process runs multiple times, the Signal stream may only return +one signal notification. Specifically, before poll is called, all +signal notifications are coalesced into one item returned from poll. +Once poll has been called, however, a further signal is guaranteed to +be yielded as an item.

    +

    Put another way, any element pulled off the returned listener corresponds to +at least one signal, but possibly more.

    +
  • +
  • +

    Signal handling in general is relatively inefficient. Although some +improvements are possible in this crate, it’s recommended to not plan on +having millions of signal channels open.

    +
  • +
+

If you’ve got any questions about this feel free to open an issue on the +repo! New approaches to alleviate some of these limitations are always +appreciated!

+

§Caveats

+

The first time that a Signal instance is registered for a particular +signal kind, an OS signal-handler is installed which replaces the default +platform behavior when that signal is received, for the duration of the +entire process.

+

For example, Unix systems will terminate a process by default when it +receives SIGINT. But, when a Signal instance is created to listen for +this signal, the next SIGINT that arrives will be translated to a stream +event, and the process will continue to execute. Even if this Signal +instance is dropped, subsequent SIGINT deliveries will end up captured by +Tokio, and the default platform behavior will NOT be reset.

+

Thus, applications should take care to ensure the expected signal behavior +occurs as expected after listening for specific signals.

+

§Examples

+

Wait for SIGHUP

+ +
use tokio::signal::unix::{signal, SignalKind};
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+    // An infinite stream of hangup signals.
+    let mut sig = signal(SignalKind::hangup())?;
+
+    // Print whenever a HUP signal is received
+    loop {
+        sig.recv().await;
+        println!("got signal HUP");
+    }
+}
+

Implementations§

§

impl Signal

pub async fn recv(&mut self) -> Option<()>

Receives the next signal notification event.

+

None is returned if no more events can be received by this stream.

+
§Cancel safety
+

This method is cancel safe. If you use it as the event in a +tokio::select! statement and some other branch +completes first, then it is guaranteed that no signal is lost.

+
§Examples
+

Wait for SIGHUP

+ +
use tokio::signal::unix::{signal, SignalKind};
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+    // An infinite stream of hangup signals.
+    let mut stream = signal(SignalKind::hangup())?;
+
+    // Print whenever a HUP signal is received
+    loop {
+        stream.recv().await;
+        println!("got signal HUP");
+    }
+}
+

pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>>

Polls to receive the next signal notification event, outside of an +async context.

+

This method returns:

+
    +
  • Poll::Pending if no signals are available but the channel is not +closed.
  • +
  • Poll::Ready(Some(())) if a signal is available.
  • +
  • Poll::Ready(None) if the channel has been closed and all signals +sent before it was closed have been received.
  • +
+
§Examples
+

Polling from a manually implemented future

+ +
use std::pin::Pin;
+use std::future::Future;
+use std::task::{Context, Poll};
+use tokio::signal::unix::Signal;
+
+struct MyFuture {
+    signal: Signal,
+}
+
+impl Future for MyFuture {
+    type Output = Option<()>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        println!("polling MyFuture");
+        self.signal.poll_recv(cx)
+    }
+}
+

Trait Implementations§

§

impl Debug for Signal

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Signal

§

impl !RefUnwindSafe for Signal

§

impl Send for Signal

§

impl Sync for Signal

§

impl Unpin for Signal

§

impl !UnwindSafe for Signal

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/signal/unix/struct.SignalKind.html b/actix_rt/signal/unix/struct.SignalKind.html new file mode 100644 index 00000000..7d59930c --- /dev/null +++ b/actix_rt/signal/unix/struct.SignalKind.html @@ -0,0 +1,63 @@ +SignalKind in actix_rt::signal::unix - Rust
actix_rt::signal::unix

Struct SignalKind

pub struct SignalKind(/* private fields */);
Expand description

Represents the specific kind of signal to listen for.

+

Implementations§

§

impl SignalKind

pub const fn from_raw(signum: i32) -> SignalKind

Allows for listening to any valid OS signal.

+

For example, this can be used for listening for platform-specific +signals.

+ +
// let signum = libc::OS_SPECIFIC_SIGNAL;
+let kind = SignalKind::from_raw(signum);
+

pub const fn as_raw_value(&self) -> i32

Get the signal’s numeric value.

+ +
let kind = SignalKind::interrupt();
+assert_eq!(kind.as_raw_value(), libc::SIGINT);
+

pub const fn alarm() -> SignalKind

Represents the SIGALRM signal.

+

On Unix systems this signal is sent when a real-time timer has expired. +By default, the process is terminated by this signal.

+

pub const fn child() -> SignalKind

Represents the SIGCHLD signal.

+

On Unix systems this signal is sent when the status of a child process +has changed. By default, this signal is ignored.

+

pub const fn hangup() -> SignalKind

Represents the SIGHUP signal.

+

On Unix systems this signal is sent when the terminal is disconnected. +By default, the process is terminated by this signal.

+

pub const fn interrupt() -> SignalKind

Represents the SIGINT signal.

+

On Unix systems this signal is sent to interrupt a program. +By default, the process is terminated by this signal.

+

pub const fn io() -> SignalKind

Represents the SIGIO signal.

+

On Unix systems this signal is sent when I/O operations are possible +on some file descriptor. By default, this signal is ignored.

+

pub const fn pipe() -> SignalKind

Represents the SIGPIPE signal.

+

On Unix systems this signal is sent when the process attempts to write +to a pipe which has no reader. By default, the process is terminated by +this signal.

+

pub const fn quit() -> SignalKind

Represents the SIGQUIT signal.

+

On Unix systems this signal is sent to issue a shutdown of the +process, after which the OS will dump the process core. +By default, the process is terminated by this signal.

+

pub const fn terminate() -> SignalKind

Represents the SIGTERM signal.

+

On Unix systems this signal is sent to issue a shutdown of the +process. By default, the process is terminated by this signal.

+

pub const fn user_defined1() -> SignalKind

Represents the SIGUSR1 signal.

+

On Unix systems this is a user defined signal. +By default, the process is terminated by this signal.

+

pub const fn user_defined2() -> SignalKind

Represents the SIGUSR2 signal.

+

On Unix systems this is a user defined signal. +By default, the process is terminated by this signal.

+

pub const fn window_change() -> SignalKind

Represents the SIGWINCH signal.

+

On Unix systems this signal is sent when the terminal window is resized. +By default, this signal is ignored.

+

Trait Implementations§

§

impl Clone for SignalKind

§

fn clone(&self) -> SignalKind

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for SignalKind

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl From<i32> for SignalKind

§

fn from(signum: i32) -> SignalKind

Converts to this type from the input type.
§

impl Hash for SignalKind

§

fn hash<__H>(&self, state: &mut __H)
where + __H: Hasher,

Feeds this value into the given Hasher. Read more
1.6.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + H: Hasher, + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
§

impl PartialEq for SignalKind

§

fn eq(&self, other: &SignalKind) -> bool

Tests for self and other values to be equal, and is used by ==.
1.6.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
§

impl Copy for SignalKind

§

impl Eq for SignalKind

§

impl StructuralPartialEq for SignalKind

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/struct.Arbiter.html b/actix_rt/struct.Arbiter.html new file mode 100644 index 00000000..eb28be9d --- /dev/null +++ b/actix_rt/struct.Arbiter.html @@ -0,0 +1,37 @@ +Arbiter in actix_rt - Rust
actix_rt

Struct Arbiter

source
pub struct Arbiter { /* private fields */ }
Expand description

An Arbiter represents a thread that provides an asynchronous execution environment for futures +and functions.

+

When an arbiter is created, it spawns a new OS thread, and hosts an event loop.

+

Implementations§

source§

impl Arbiter

source

pub fn new() -> Arbiter

Spawn a new Arbiter thread and start its event loop with tokio-uring runtime.

+
§Panics
+

Panics if a System is not registered on the current thread.

+
source

pub fn handle(&self) -> ArbiterHandle

Return a handle to the this Arbiter’s message sender.

+
source

pub fn current() -> ArbiterHandle

Return a handle to the current thread’s Arbiter’s message sender.

+
§Panics
+

Panics if no Arbiter is running on the current thread.

+
source

pub fn try_current() -> Option<ArbiterHandle>

Try to get current running arbiter handle.

+

Returns None if no Arbiter has been started.

+

Unlike current, this never panics.

+
source

pub fn stop(&self) -> bool

Stop Arbiter from continuing it’s event loop.

+

Returns true if stop message was sent successfully and false if the Arbiter has been dropped.

+
source

pub fn spawn<Fut>(&self, future: Fut) -> bool
where + Fut: Future<Output = ()> + Send + 'static,

Send a future to the Arbiter’s thread and spawn it.

+

If you require a result, include a response channel in the future.

+

Returns true if future was sent successfully and false if the Arbiter has died.

+
source

pub fn spawn_fn<F>(&self, f: F) -> bool
where + F: FnOnce() + Send + 'static,

Send a function to the Arbiter’s thread and execute it.

+

Any result from the function is discarded. If you require a result, include a response +channel in the function.

+

Returns true if function was sent successfully and false if the Arbiter has died.

+
source

pub fn join(self) -> Result<()>

Wait for Arbiter’s event loop to complete.

+

Joins the underlying OS thread handle. See JoinHandle::join.

+

Trait Implementations§

source§

impl Debug for Arbiter

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/struct.ArbiterHandle.html b/actix_rt/struct.ArbiterHandle.html new file mode 100644 index 00000000..42b60cf3 --- /dev/null +++ b/actix_rt/struct.ArbiterHandle.html @@ -0,0 +1,26 @@ +ArbiterHandle in actix_rt - Rust
actix_rt

Struct ArbiterHandle

source
pub struct ArbiterHandle { /* private fields */ }
Expand description

A handle for sending spawn and stop messages to an Arbiter.

+

Implementations§

source§

impl ArbiterHandle

source

pub fn spawn<Fut>(&self, future: Fut) -> bool
where + Fut: Future<Output = ()> + Send + 'static,

Send a future to the Arbiter’s thread and spawn it.

+

If you require a result, include a response channel in the future.

+

Returns true if future was sent successfully and false if the Arbiter has died.

+
source

pub fn spawn_fn<F>(&self, f: F) -> bool
where + F: FnOnce() + Send + 'static,

Send a function to the Arbiter’s thread and execute it.

+

Any result from the function is discarded. If you require a result, include a response +channel in the function.

+

Returns true if function was sent successfully and false if the Arbiter has died.

+
source

pub fn stop(&self) -> bool

Instruct Arbiter to stop processing it’s event loop.

+

Returns true if stop message was sent successfully and false if the Arbiter has +been dropped.

+

Trait Implementations§

source§

impl Clone for ArbiterHandle

source§

fn clone(&self) -> ArbiterHandle

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for ArbiterHandle

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/struct.Runtime.html b/actix_rt/struct.Runtime.html new file mode 100644 index 00000000..e47e8e2e --- /dev/null +++ b/actix_rt/struct.Runtime.html @@ -0,0 +1,85 @@ +Runtime in actix_rt - Rust
actix_rt

Struct Runtime

source
pub struct Runtime { /* private fields */ }
Expand description

A Tokio-based runtime proxy.

+

All spawned futures will be executed on the current thread. Therefore, there is no Send bound +on submitted futures.

+

Implementations§

source§

impl Runtime

source

pub fn new() -> Result<Self>

Returns a new runtime initialized with default configuration values.

+
source

pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
where + F: Future + 'static,

Offload a future onto the single-threaded runtime.

+

The returned join handle can be used to await the future’s result.

+

See crate root documentation for more details.

+
§Examples
+
let rt = actix_rt::Runtime::new().unwrap();
+
+// Spawn a future onto the runtime
+let handle = rt.spawn(async {
+    println!("running on the runtime");
+    42
+});
+
+assert_eq!(rt.block_on(handle).unwrap(), 42);
+
§Panics
+

This function panics if the spawn fails. Failure occurs if the executor is currently at +capacity and is unable to spawn a new future.

+
source

pub fn tokio_runtime(&self) -> &Runtime

Retrieves a reference to the underlying Tokio runtime associated with this instance.

+

The Tokio runtime is responsible for executing asynchronous tasks and managing +the event loop for an asynchronous Rust program. This method allows accessing +the runtime to interact with its features directly.

+

In a typical use case, you might need to share the same runtime between different +modules of your project. For example, a module might require a tokio::runtime::Handle +to spawn tasks on the same runtime, or the runtime itself to configure more complex +behaviours.

+
§Example
+
use actix_rt::Runtime;
+
+mod module_a {
+    pub fn do_something(handle: tokio::runtime::Handle) {
+        handle.spawn(async {
+            // Some asynchronous task here
+        });
+    }
+}
+
+mod module_b {
+    pub fn do_something_else(rt: &tokio::runtime::Runtime) {
+        rt.spawn(async {
+            // Another asynchronous task here
+        });
+    }
+}
+
+let actix_runtime = actix_rt::Runtime::new().unwrap();
+let tokio_runtime = actix_runtime.tokio_runtime();
+
+let handle = tokio_runtime.handle().clone();
+
+module_a::do_something(handle);
+module_b::do_something_else(tokio_runtime);
+
§Returns
+

An immutable reference to the tokio::runtime::Runtime instance associated with this +Runtime instance.

+
§Note
+

While this method provides an immutable reference to the Tokio runtime, which is safe to share across threads, +be aware that spawning blocking tasks on the Tokio runtime could potentially impact the execution +of the Actix runtime. This is because Tokio is responsible for driving the Actix system, +and blocking tasks could delay or deadlock other tasks in run loop.

+
source

pub fn block_on<F>(&self, f: F) -> F::Output
where + F: Future,

Runs the provided future, blocking the current thread until the future completes.

+

This function can be used to synchronously block the current thread until the provided +future has resolved either successfully or with an error. The result of the future is +then returned from this function call.

+

Note that this function will also execute any spawned futures on the current thread, but +will not block until these other spawned futures have completed. Once the function returns, +any uncompleted futures remain pending in the Runtime instance. These futures will not run +until block_on or run is called again.

+

The caller is responsible for ensuring that other spawned futures complete execution by +calling block_on or run.

+

Trait Implementations§

source§

impl Debug for Runtime

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<Runtime> for Runtime

source§

fn from(rt: Runtime) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl !Freeze for Runtime

§

impl !RefUnwindSafe for Runtime

§

impl !Send for Runtime

§

impl !Sync for Runtime

§

impl Unpin for Runtime

§

impl !UnwindSafe for Runtime

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/struct.System.html b/actix_rt/struct.System.html new file mode 100644 index 00000000..985a279f --- /dev/null +++ b/actix_rt/struct.System.html @@ -0,0 +1,29 @@ +System in actix_rt - Rust
actix_rt

Struct System

source
pub struct System { /* private fields */ }
Expand description

A manager for a per-thread distributed async runtime.

+

Implementations§

source§

impl System

source

pub fn new() -> SystemRunner

Create a new system.

+
§Panics
+

Panics if underlying Tokio runtime can not be created.

+
source§

impl System

source

pub fn current() -> System

Get current running system.

+
§Panics
+

Panics if no system is registered on the current thread.

+
source

pub fn try_current() -> Option<System>

Try to get current running system.

+

Returns None if no System has been started.

+

Unlike current, this never panics.

+
source

pub fn arbiter(&self) -> &ArbiterHandle

Get handle to a the System’s initial Arbiter.

+
source

pub fn is_registered() -> bool

Check if there is a System registered on the current thread.

+
source

pub fn id(&self) -> usize

Numeric system identifier.

+

Useful when using multiple Systems.

+
source

pub fn stop(&self)

Stop the system (with code 0).

+
source

pub fn stop_with_code(&self, code: i32)

Stop the system with a given exit code.

+

Trait Implementations§

source§

impl Clone for System

source§

fn clone(&self) -> System

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for System

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for System

§

impl RefUnwindSafe for System

§

impl Send for System

§

impl Sync for System

§

impl Unpin for System

§

impl UnwindSafe for System

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/struct.SystemRunner.html b/actix_rt/struct.SystemRunner.html new file mode 100644 index 00000000..cda32b9e --- /dev/null +++ b/actix_rt/struct.SystemRunner.html @@ -0,0 +1,15 @@ +SystemRunner in actix_rt - Rust
actix_rt

Struct SystemRunner

source
pub struct SystemRunner;
Expand description

Runner that keeps a System’s event loop alive until stop message is received.

+

Implementations§

source§

impl SystemRunner

source

pub fn run(self) -> Result<()>

Starts event loop and will return once System is stopped.

+
source

pub fn run_with_code(self) -> Result<i32>

Runs the event loop until stopped, returning the exit code.

+
source

pub fn block_on<F: Future>(&self, fut: F) -> F::Output

Runs the provided future, blocking the current thread until the future completes.

+

Trait Implementations§

source§

impl Debug for SystemRunner

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/system/struct.System.html b/actix_rt/system/struct.System.html new file mode 100644 index 00000000..aff72509 --- /dev/null +++ b/actix_rt/system/struct.System.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_rt/struct.System.html...

+ + + \ No newline at end of file diff --git a/actix_rt/system/struct.SystemRunner.html b/actix_rt/system/struct.SystemRunner.html new file mode 100644 index 00000000..3324e830 --- /dev/null +++ b/actix_rt/system/struct.SystemRunner.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_rt/struct.SystemRunner.html...

+ + + \ No newline at end of file diff --git a/actix_rt/task/fn.spawn_blocking.html b/actix_rt/task/fn.spawn_blocking.html new file mode 100644 index 00000000..05a06acf --- /dev/null +++ b/actix_rt/task/fn.spawn_blocking.html @@ -0,0 +1,86 @@ +spawn_blocking in actix_rt::task - Rust
actix_rt::task

Function spawn_blocking

pub fn spawn_blocking<F, R>(f: F) -> JoinHandle<R> 
where + F: FnOnce() -> R + Send + 'static, + R: Send + 'static,
Expand description

Runs the provided closure on a thread where blocking is acceptable.

+

In general, issuing a blocking call or performing a lot of compute in a +future without yielding is problematic, as it may prevent the executor from +driving other futures forward. This function runs the provided closure on a +thread dedicated to blocking operations. See the CPU-bound tasks and +blocking code section for more information.

+

Tokio will spawn more blocking threads when they are requested through this +function until the upper limit configured on the Builder is reached. +After reaching the upper limit, the tasks are put in a queue. +The thread limit is very large by default, because spawn_blocking is often +used for various kinds of IO operations that cannot be performed +asynchronously. When you run CPU-bound code using spawn_blocking, you +should keep this large upper limit in mind. When running many CPU-bound +computations, a semaphore or some other synchronization primitive should be +used to limit the number of computation executed in parallel. Specialized +CPU-bound executors, such as rayon, may also be a good fit.

+

This function is intended for non-async operations that eventually finish on +their own. If you want to spawn an ordinary thread, you should use +thread::spawn instead.

+

Be aware that tasks spawned using spawn_blocking cannot be aborted +because they are not async. If you call abort on a spawn_blocking +task, then this will not have any effect, and the task will continue +running normally. The exception is if the task has not started running +yet; in that case, calling abort may prevent the task from starting.

+

When you shut down the executor, it will wait indefinitely for all blocking operations to +finish. You can use shutdown_timeout to stop waiting for them after a +certain timeout. Be aware that this will still not cancel the tasks — they +are simply allowed to keep running after the method returns. It is possible +for a blocking task to be cancelled if it has not yet started running, but this +is not guaranteed.

+

Note that if you are using the single threaded runtime, this function will +still spawn additional threads for blocking operations. The current-thread +scheduler’s single thread is only used for asynchronous code.

+ +

In simple cases, it is sufficient to have the closure accept input +parameters at creation time and return a single value (or struct/tuple, etc.).

+

For more complex situations in which it is desirable to stream data to or from +the synchronous context, the mpsc channel has blocking_send and +blocking_recv methods for use in non-async code such as the thread created +by spawn_blocking.

+

Another option is SyncIoBridge for cases where the synchronous context +is operating on byte streams. For example, you might use an asynchronous +HTTP client such as hyper to fetch data, but perform complex parsing +of the payload body using a library written for synchronous I/O.

+

Finally, see also Bridging with sync code for discussions +around the opposite case of using Tokio as part of a larger synchronous +codebase.

+

§Examples

+

Pass an input value and receive result of computation:

+ +
use tokio::task;
+
+// Initial input
+let mut v = "Hello, ".to_string();
+let res = task::spawn_blocking(move || {
+    // Stand-in for compute-heavy work or using synchronous APIs
+    v.push_str("world");
+    // Pass ownership of the value back to the asynchronous context
+    v
+}).await?;
+
+// `res` is the value returned from the thread
+assert_eq!(res.as_str(), "Hello, world");
+

Use a channel:

+ +
use tokio::task;
+use tokio::sync::mpsc;
+
+let (tx, mut rx) = mpsc::channel(2);
+let start = 5;
+let worker = task::spawn_blocking(move || {
+    for x in 0..10 {
+        // Stand in for complex computation
+        tx.blocking_send(start + x).unwrap();
+    }
+});
+
+let mut acc = 0;
+while let Some(v) = rx.recv().await {
+    acc += v;
+}
+assert_eq!(acc, 95);
+worker.await.unwrap();
+
\ No newline at end of file diff --git a/actix_rt/task/fn.yield_now.html b/actix_rt/task/fn.yield_now.html new file mode 100644 index 00000000..71589fc6 --- /dev/null +++ b/actix_rt/task/fn.yield_now.html @@ -0,0 +1,24 @@ +yield_now in actix_rt::task - Rust
actix_rt::task

Function yield_now

pub async fn yield_now()
Expand description

Yields execution back to the Tokio runtime.

+

A task yields by awaiting on yield_now(), and may resume when that future +completes (with no output.) The current task will be re-added as a pending +task at the back of the pending queue. Any other pending tasks will be +scheduled. No other waking is required for the task to continue.

+

See also the usage example in the task module.

+

§Non-guarantees

+

This function may not yield all the way up to the executor if there are any +special combinators above it in the call stack. For example, if a +tokio::select! has another branch complete during the same poll as the +yield_now(), then the yield is not propagated all the way up to the +runtime.

+

It is generally not guaranteed that the runtime behaves like you expect it +to when deciding which task to schedule next after a call to yield_now(). +In particular, the runtime may choose to poll the task that just ran +yield_now() again immediately without polling any other tasks first. For +example, the runtime will not drive the IO driver between every poll of a +task, and this could result in the runtime polling the current task again +immediately even if there is another task that could make progress if that +other task is waiting for a notification from the IO driver.

+

In general, changes to the order in which the runtime polls tasks is not +considered a breaking change, and your program should be correct no matter +which order the runtime polls your tasks in.

+
\ No newline at end of file diff --git a/actix_rt/task/index.html b/actix_rt/task/index.html new file mode 100644 index 00000000..8f0b7323 --- /dev/null +++ b/actix_rt/task/index.html @@ -0,0 +1,2 @@ +actix_rt::task - Rust
actix_rt

Module task

source
Expand description

Task management (Tokio re-exports).

+

Structs§

  • Task failed to execute to completion.
  • An owned permission to join on a task (await its termination).

Functions§

  • Runs the provided closure on a thread where blocking is acceptable.
  • Yields execution back to the Tokio runtime.
\ No newline at end of file diff --git a/actix_rt/task/sidebar-items.js b/actix_rt/task/sidebar-items.js new file mode 100644 index 00000000..e5d1fa75 --- /dev/null +++ b/actix_rt/task/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["spawn_blocking","yield_now"],"struct":["JoinError","JoinHandle"]}; \ No newline at end of file diff --git a/actix_rt/task/struct.JoinError.html b/actix_rt/task/struct.JoinError.html new file mode 100644 index 00000000..2db73c60 --- /dev/null +++ b/actix_rt/task/struct.JoinError.html @@ -0,0 +1,63 @@ +JoinError in actix_rt::task - Rust
actix_rt::task

Struct JoinError

pub struct JoinError { /* private fields */ }
Expand description

Task failed to execute to completion.

+

Implementations§

§

impl JoinError

pub fn is_cancelled(&self) -> bool

Returns true if the error was caused by the task being cancelled.

+

See the module level docs for more information on cancellation.

+

pub fn is_panic(&self) -> bool

Returns true if the error was caused by the task panicking.

+
§Examples
+
use std::panic;
+
+#[tokio::main]
+async fn main() {
+    let err = tokio::spawn(async {
+        panic!("boom");
+    }).await.unwrap_err();
+
+    assert!(err.is_panic());
+}
+

pub fn into_panic(self) -> Box<dyn Any + Send>

Consumes the join error, returning the object with which the task panicked.

+
§Panics
+

into_panic() panics if the Error does not represent the underlying +task terminating with a panic. Use is_panic to check the error reason +or try_into_panic for a variant that does not panic.

+
§Examples
+
use std::panic;
+
+#[tokio::main]
+async fn main() {
+    let err = tokio::spawn(async {
+        panic!("boom");
+    }).await.unwrap_err();
+
+    if err.is_panic() {
+        // Resume the panic on the main task
+        panic::resume_unwind(err.into_panic());
+    }
+}
+

pub fn try_into_panic(self) -> Result<Box<dyn Any + Send>, JoinError>

Consumes the join error, returning the object with which the task +panicked if the task terminated due to a panic. Otherwise, self is +returned.

+
§Examples
+
use std::panic;
+
+#[tokio::main]
+async fn main() {
+    let err = tokio::spawn(async {
+        panic!("boom");
+    }).await.unwrap_err();
+
+    if let Ok(reason) = err.try_into_panic() {
+        // Resume the panic on the main task
+        panic::resume_unwind(reason);
+    }
+}
+

Trait Implementations§

§

impl Debug for JoinError

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Display for JoinError

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Error for JoinError

1.81.0 · source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/task/struct.JoinHandle.html b/actix_rt/task/struct.JoinHandle.html new file mode 100644 index 00000000..21c838a7 --- /dev/null +++ b/actix_rt/task/struct.JoinHandle.html @@ -0,0 +1,291 @@ +JoinHandle in actix_rt::task - Rust
actix_rt::task

Struct JoinHandle

pub struct JoinHandle<T> { /* private fields */ }
Expand description

An owned permission to join on a task (await its termination).

+

This can be thought of as the equivalent of std::thread::JoinHandle +for a Tokio task rather than a thread. Note that the background task +associated with this JoinHandle started running immediately when you +called spawn, even if you have not yet awaited the JoinHandle.

+

A JoinHandle detaches the associated task when it is dropped, which +means that there is no longer any handle to the task, and no way to join +on it.

+

This struct is created by the task::spawn and task::spawn_blocking +functions.

+

§Cancel safety

+

The &mut JoinHandle<T> type is cancel safe. If it is used as the event +in a tokio::select! statement and some other branch completes first, +then it is guaranteed that the output of the task is not lost.

+

If a JoinHandle is dropped, then the task continues running in the +background and its return value is lost.

+

§Examples

+

Creation from task::spawn:

+ +
use tokio::task;
+
+let join_handle: task::JoinHandle<_> = task::spawn(async {
+    // some work here
+});
+

Creation from task::spawn_blocking:

+ +
use tokio::task;
+
+let join_handle: task::JoinHandle<_> = task::spawn_blocking(|| {
+    // some blocking work here
+});
+

The generic parameter T in JoinHandle<T> is the return type of the spawned task. +If the return value is an i32, the join handle has type JoinHandle<i32>:

+ +
use tokio::task;
+
+let join_handle: task::JoinHandle<i32> = task::spawn(async {
+    5 + 3
+});
+
+

If the task does not have a return value, the join handle has type JoinHandle<()>:

+ +
use tokio::task;
+
+let join_handle: task::JoinHandle<()> = task::spawn(async {
+    println!("I return nothing.");
+});
+

Note that handle.await doesn’t give you the return type directly. It is wrapped in a +Result because panics in the spawned task are caught by Tokio. The ? operator has +to be double chained to extract the returned value:

+ +
use tokio::task;
+use std::io;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
+        Ok(5 + 3)
+    });
+
+    let result = join_handle.await??;
+    assert_eq!(result, 8);
+    Ok(())
+}
+

If the task panics, the error is a JoinError that contains the panic:

+ +
use tokio::task;
+use std::io;
+use std::panic;
+
+#[tokio::main]
+async fn main() -> io::Result<()> {
+    let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
+        panic!("boom");
+    });
+
+    let err = join_handle.await.unwrap_err();
+    assert!(err.is_panic());
+    Ok(())
+}
+
+

Child being detached and outliving its parent:

+ +
use tokio::task;
+use tokio::time;
+use std::time::Duration;
+
+let original_task = task::spawn(async {
+    let _detached_task = task::spawn(async {
+        // Here we sleep to make sure that the first task returns before.
+        time::sleep(Duration::from_millis(10)).await;
+        // This will be called, even though the JoinHandle is dropped.
+        println!("♫ Still alive ♫");
+    });
+});
+
+original_task.await.expect("The task being joined has panicked");
+println!("Original task is joined.");
+
+// We make sure that the new task has time to run, before the main
+// task returns.
+
+time::sleep(Duration::from_millis(1000)).await;
+

Implementations§

§

impl<T> JoinHandle<T>

pub fn abort(&self)

Abort the task associated with the handle.

+

Awaiting a cancelled task might complete as usual if the task was +already completed at the time it was cancelled, but most likely it +will fail with a cancelled JoinError.

+

Be aware that tasks spawned using spawn_blocking cannot be aborted +because they are not async. If you call abort on a spawn_blocking +task, then this will not have any effect, and the task will continue +running normally. The exception is if the task has not started running +yet; in that case, calling abort may prevent the task from starting.

+

See also the module level docs for more information on cancellation.

+ +
use tokio::time;
+
+let mut handles = Vec::new();
+
+handles.push(tokio::spawn(async {
+   time::sleep(time::Duration::from_secs(10)).await;
+   true
+}));
+
+handles.push(tokio::spawn(async {
+   time::sleep(time::Duration::from_secs(10)).await;
+   false
+}));
+
+for handle in &handles {
+    handle.abort();
+}
+
+for handle in handles {
+    assert!(handle.await.unwrap_err().is_cancelled());
+}
+

pub fn is_finished(&self) -> bool

Checks if the task associated with this JoinHandle has finished.

+

Please note that this method can return false even if abort has been +called on the task. This is because the cancellation process may take +some time, and this method does not return true until it has +completed.

+ +
use tokio::time;
+
+let handle1 = tokio::spawn(async {
+    // do some stuff here
+});
+let handle2 = tokio::spawn(async {
+    // do some other stuff here
+    time::sleep(time::Duration::from_secs(10)).await;
+});
+// Wait for the task to finish
+handle2.abort();
+time::sleep(time::Duration::from_secs(1)).await;
+assert!(handle1.is_finished());
+assert!(handle2.is_finished());
+

pub fn abort_handle(&self) -> AbortHandle

Returns a new AbortHandle that can be used to remotely abort this task.

+

Awaiting a task cancelled by the AbortHandle might complete as usual if the task was +already completed at the time it was cancelled, but most likely it +will fail with a cancelled JoinError.

+ +
use tokio::{time, task};
+
+let mut handles = Vec::new();
+
+handles.push(tokio::spawn(async {
+   time::sleep(time::Duration::from_secs(10)).await;
+   true
+}));
+
+handles.push(tokio::spawn(async {
+   time::sleep(time::Duration::from_secs(10)).await;
+   false
+}));
+
+let abort_handles: Vec<task::AbortHandle> = handles.iter().map(|h| h.abort_handle()).collect();
+
+for handle in abort_handles {
+    handle.abort();
+}
+
+for handle in handles {
+    assert!(handle.await.unwrap_err().is_cancelled());
+}
+

Trait Implementations§

§

impl<T> Debug for JoinHandle<T>
where + T: Debug,

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<T> Drop for JoinHandle<T>

§

fn drop(&mut self)

Executes the destructor for this type. Read more
§

impl<T> Future for JoinHandle<T>

§

type Output = Result<T, JoinError>

The type of value produced on completion.
§

fn poll( + self: Pin<&mut JoinHandle<T>>, + cx: &mut Context<'_>, +) -> Poll<<JoinHandle<T> as Future>::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
§

impl<T> RefUnwindSafe for JoinHandle<T>

§

impl<T> Send for JoinHandle<T>
where + T: Send,

§

impl<T> Sync for JoinHandle<T>
where + T: Send,

§

impl<T> Unpin for JoinHandle<T>

§

impl<T> UnwindSafe for JoinHandle<T>

Auto Trait Implementations§

§

impl<T> Freeze for JoinHandle<T>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> FutureExt for T
where + T: Future + ?Sized,

§

fn map<U, F>(self, f: F) -> Map<Self, F>
where + F: FnOnce(Self::Output) -> U, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn map_into<U>(self) -> MapInto<Self, U>
where + Self::Output: Into<U>, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
where + F: FnOnce(Self::Output) -> Fut, + Fut: Future, + Self: Sized,

Chain on a computation for when a future finished, passing the result of +the future to the provided closure f. Read more
§

fn left_future<B>(self) -> Either<Self, B>
where + B: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the left-hand variant +of that Either. Read more
§

fn right_future<A>(self) -> Either<A, Self>
where + A: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the right-hand variant +of that Either. Read more
§

fn into_stream(self) -> IntoStream<Self>
where + Self: Sized,

Convert this future into a single element stream. Read more
§

fn flatten(self) -> Flatten<Self>
where + Self::Output: Future, + Self: Sized,

Flatten the execution of this future when the output of this +future is itself another future. Read more
§

fn flatten_stream(self) -> FlattenStream<Self>
where + Self::Output: Stream, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is a stream. Read more
§

fn fuse(self) -> Fuse<Self>
where + Self: Sized,

Fuse a future such that poll will never again be called once it has +completed. This method can be used to turn any Future into a +FusedFuture. Read more
§

fn inspect<F>(self, f: F) -> Inspect<Self, F>
where + F: FnOnce(&Self::Output), + Self: Sized,

Do something with the output of a future before passing it on. Read more
§

fn catch_unwind(self) -> CatchUnwind<Self>
where + Self: Sized + UnwindSafe,

Catches unwinding panics while polling the future. Read more
§

fn shared(self) -> Shared<Self>
where + Self: Sized, + Self::Output: Clone,

Create a cloneable handle to this future where all handles will resolve +to the same result. Read more
§

fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
where + Self: Sized + Send + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>
where + Self: Sized + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn unit_error(self) -> UnitError<Self>
where + Self: Sized,

§

fn never_error(self) -> NeverError<Self>
where + Self: Sized,

§

fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
where + Self: Unpin,

A convenience for calling Future::poll on Unpin future types.
§

fn now_or_never(self) -> Option<Self::Output>
where + Self: Sized,

Evaluates and consumes the future, returning the resulting output if +the future is ready after the first call to Future::poll. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<F> IntoFuture for F
where + F: Future,

source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
source§

type IntoFuture = F

Which kind of future are we turning this into?
source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<F, T, E> TryFuture for F
where + F: Future<Output = Result<T, E>> + ?Sized,

§

type Ok = T

The type of successful values yielded by this future
§

type Error = E

The type of failures yielded by this future
§

fn try_poll( + self: Pin<&mut F>, + cx: &mut Context<'_>, +) -> Poll<<F as Future>::Output>

Poll this TryFuture as if it were a Future. Read more
§

impl<Fut> TryFutureExt for Fut
where + Fut: TryFuture + ?Sized,

§

fn map_ok<T, F>(self, f: F) -> MapOk<Self, F>
where + F: FnOnce(Self::Ok) -> T, + Self: Sized,

Maps this future’s success value to a different value. Read more
§

fn map_ok_or_else<T, E, F>(self, e: E, f: F) -> MapOkOrElse<Self, F, E>
where + F: FnOnce(Self::Ok) -> T, + E: FnOnce(Self::Error) -> T, + Self: Sized,

Maps this future’s success value to a different value, and permits for error handling resulting in the same type. Read more
§

fn map_err<E, F>(self, f: F) -> MapErr<Self, F>
where + F: FnOnce(Self::Error) -> E, + Self: Sized,

Maps this future’s error value to a different value. Read more
§

fn err_into<E>(self) -> ErrInto<Self, E>
where + Self: Sized, + Self::Error: Into<E>,

Maps this future’s Error to a new error type +using the Into trait. Read more
§

fn ok_into<U>(self) -> OkInto<Self, U>
where + Self: Sized, + Self::Ok: Into<U>,

Maps this future’s Ok to a new type +using the Into trait.
§

fn and_then<Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
where + F: FnOnce(Self::Ok) -> Fut, + Fut: TryFuture<Error = Self::Error>, + Self: Sized,

Executes another future after this one resolves successfully. The +success value is passed to a closure to create this subsequent future. Read more
§

fn or_else<Fut, F>(self, f: F) -> OrElse<Self, Fut, F>
where + F: FnOnce(Self::Error) -> Fut, + Fut: TryFuture<Ok = Self::Ok>, + Self: Sized,

Executes another future if this one resolves to an error. The +error value is passed to a closure to create this subsequent future. Read more
§

fn inspect_ok<F>(self, f: F) -> InspectOk<Self, F>
where + F: FnOnce(&Self::Ok), + Self: Sized,

Do something with the success value of a future before passing it on. Read more
§

fn inspect_err<F>(self, f: F) -> InspectErr<Self, F>
where + F: FnOnce(&Self::Error), + Self: Sized,

Do something with the error value of a future before passing it on. Read more
§

fn try_flatten(self) -> TryFlatten<Self, Self::Ok>
where + Self::Ok: TryFuture<Error = Self::Error>, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is another future. Read more
§

fn try_flatten_stream(self) -> TryFlattenStream<Self>
where + Self::Ok: TryStream<Error = Self::Error>, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is a stream. Read more
§

fn unwrap_or_else<F>(self, f: F) -> UnwrapOrElse<Self, F>
where + Self: Sized, + F: FnOnce(Self::Error) -> Self::Ok,

Unwraps this future’s output, producing a future with this future’s +Ok type as its +Output type. Read more
§

fn into_future(self) -> IntoFuture<Self>
where + Self: Sized,

Wraps a [TryFuture] into a type that implements +Future. Read more
§

fn try_poll_unpin( + &mut self, + cx: &mut Context<'_>, +) -> Poll<Result<Self::Ok, Self::Error>>
where + Self: Unpin,

A convenience method for calling [TryFuture::try_poll] on Unpin +future types.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/time/fn.interval.html b/actix_rt/time/fn.interval.html new file mode 100644 index 00000000..b54dd1d2 --- /dev/null +++ b/actix_rt/time/fn.interval.html @@ -0,0 +1,48 @@ +interval in actix_rt::time - Rust
actix_rt::time

Function interval

pub fn interval(period: Duration) -> Interval
Expand description

Creates new Interval that yields with interval of period. The first +tick completes immediately. The default [MissedTickBehavior] is +Burst, but this can be configured +by calling set_missed_tick_behavior.

+

An interval will tick indefinitely. At any time, the Interval value can +be dropped. This cancels the interval.

+

This function is equivalent to +interval_at(Instant::now(), period).

+

§Panics

+

This function panics if period is zero.

+

§Examples

+
use tokio::time::{self, Duration};
+
+#[tokio::main]
+async fn main() {
+    let mut interval = time::interval(Duration::from_millis(10));
+
+    interval.tick().await; // ticks immediately
+    interval.tick().await; // ticks after 10ms
+    interval.tick().await; // ticks after 10ms
+
+    // approximately 20ms have elapsed.
+}
+

A simple example using interval to execute a task every two seconds.

+

The difference between interval and sleep is that an Interval +measures the time since the last tick, which means that .tick().await +may wait for a shorter time than the duration specified for the interval +if some time has passed between calls to .tick().await.

+

If the tick in the example below was replaced with sleep, the task +would only be executed once every three seconds, and not every two +seconds.

+ +
use tokio::time;
+
+async fn task_that_takes_a_second() {
+    println!("hello");
+    time::sleep(time::Duration::from_secs(1)).await
+}
+
+#[tokio::main]
+async fn main() {
+    let mut interval = time::interval(time::Duration::from_secs(2));
+    for _i in 0..5 {
+        interval.tick().await;
+        task_that_takes_a_second().await;
+    }
+}
+
\ No newline at end of file diff --git a/actix_rt/time/fn.interval_at.html b/actix_rt/time/fn.interval_at.html new file mode 100644 index 00000000..77c6355f --- /dev/null +++ b/actix_rt/time/fn.interval_at.html @@ -0,0 +1,23 @@ +interval_at in actix_rt::time - Rust
actix_rt::time

Function interval_at

pub fn interval_at(start: Instant, period: Duration) -> Interval
Expand description

Creates new Interval that yields with interval of period with the +first tick completing at start. The default [MissedTickBehavior] is +Burst, but this can be configured +by calling set_missed_tick_behavior.

+

An interval will tick indefinitely. At any time, the Interval value can +be dropped. This cancels the interval.

+

§Panics

+

This function panics if period is zero.

+

§Examples

+
use tokio::time::{interval_at, Duration, Instant};
+
+#[tokio::main]
+async fn main() {
+    let start = Instant::now() + Duration::from_millis(50);
+    let mut interval = interval_at(start, Duration::from_millis(10));
+
+    interval.tick().await; // ticks after 50ms
+    interval.tick().await; // ticks after 10ms
+    interval.tick().await; // ticks after 10ms
+
+    // approximately 70ms have elapsed.
+}
+
\ No newline at end of file diff --git a/actix_rt/time/fn.sleep.html b/actix_rt/time/fn.sleep.html new file mode 100644 index 00000000..dc591c20 --- /dev/null +++ b/actix_rt/time/fn.sleep.html @@ -0,0 +1,36 @@ +sleep in actix_rt::time - Rust
actix_rt::time

Function sleep

pub fn sleep(duration: Duration) -> Sleep 
Expand description

Waits until duration has elapsed.

+

Equivalent to sleep_until(Instant::now() + duration). An asynchronous +analog to std::thread::sleep.

+

No work is performed while awaiting on the sleep future to complete. Sleep +operates at millisecond granularity and should not be used for tasks that +require high-resolution timers. The implementation is platform specific, +and some platforms (specifically Windows) will provide timers with a +larger resolution than 1 ms.

+

To run something regularly on a schedule, see interval.

+

The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).

+

§Cancellation

+

Canceling a sleep instance is done by dropping the returned future. No additional +cleanup work is required.

+

§Examples

+

Wait 100ms and print “100 ms have elapsed”.

+ +
use tokio::time::{sleep, Duration};
+
+#[tokio::main]
+async fn main() {
+    sleep(Duration::from_millis(100)).await;
+    println!("100 ms have elapsed");
+}
+

See the documentation for the Sleep type for more examples.

+

§Panics

+

This function panics if there is no current timer set.

+

It can be triggered when Builder::enable_time or +Builder::enable_all are not included in the builder.

+

It can also panic whenever a timer is created outside of a +Tokio runtime. That is why rt.block_on(sleep(...)) will panic, +since the function is executed outside of the runtime. +Whereas rt.block_on(async {sleep(...).await}) doesn’t panic. +And this is because wrapping the function on an async makes it lazy, +and so gets executed inside the runtime successfully without +panicking.

+
\ No newline at end of file diff --git a/actix_rt/time/fn.sleep_until.html b/actix_rt/time/fn.sleep_until.html new file mode 100644 index 00000000..0806594f --- /dev/null +++ b/actix_rt/time/fn.sleep_until.html @@ -0,0 +1,31 @@ +sleep_until in actix_rt::time - Rust
actix_rt::time

Function sleep_until

pub fn sleep_until(deadline: Instant) -> Sleep 
Expand description

Waits until deadline is reached.

+

No work is performed while awaiting on the sleep future to complete. Sleep +operates at millisecond granularity and should not be used for tasks that +require high-resolution timers.

+

To run something regularly on a schedule, see interval.

+

§Cancellation

+

Canceling a sleep instance is done by dropping the returned future. No additional +cleanup work is required.

+

§Examples

+

Wait 100ms and print “100 ms have elapsed”.

+ +
use tokio::time::{sleep_until, Instant, Duration};
+
+#[tokio::main]
+async fn main() {
+    sleep_until(Instant::now() + Duration::from_millis(100)).await;
+    println!("100 ms have elapsed");
+}
+

See the documentation for the Sleep type for more examples.

+

§Panics

+

This function panics if there is no current timer set.

+

It can be triggered when Builder::enable_time or +Builder::enable_all are not included in the builder.

+

It can also panic whenever a timer is created outside of a +Tokio runtime. That is why rt.block_on(sleep(...)) will panic, +since the function is executed outside of the runtime. +Whereas rt.block_on(async {sleep(...).await}) doesn’t panic. +And this is because wrapping the function on an async makes it lazy, +and so gets executed inside the runtime successfully without +panicking.

+
\ No newline at end of file diff --git a/actix_rt/time/fn.timeout.html b/actix_rt/time/fn.timeout.html new file mode 100644 index 00000000..525c042b --- /dev/null +++ b/actix_rt/time/fn.timeout.html @@ -0,0 +1,47 @@ +timeout in actix_rt::time - Rust
actix_rt::time

Function timeout

pub fn timeout<F>(
+    duration: Duration,
+    future: F,
+) -> Timeout<<F as IntoFuture>::IntoFuture> 
where + F: IntoFuture,
Expand description

Requires a Future to complete before the specified duration has elapsed.

+

If the future completes before the duration has elapsed, then the completed +value is returned. Otherwise, an error is returned and the future is +canceled.

+

Note that the timeout is checked before polling the future, so if the future +does not yield during execution then it is possible for the future to complete +and exceed the timeout without returning an error.

+

This function returns a future whose return type is Result<T,Elapsed>, where T is the +return type of the provided future.

+

If the provided future completes immediately, then the future returned from +this function is guaranteed to complete immediately with an Ok variant +no matter the provided duration.

+

§Cancellation

+

Cancelling a timeout is done by dropping the future. No additional cleanup +or other work is required.

+

The original future may be obtained by calling Timeout::into_inner. This +consumes the Timeout.

+

§Examples

+

Create a new Timeout set to expire in 10 milliseconds.

+ +
use tokio::time::timeout;
+use tokio::sync::oneshot;
+
+use std::time::Duration;
+
+let (tx, rx) = oneshot::channel();
+
+// Wrap the future with a `Timeout` set to expire in 10 milliseconds.
+if let Err(_) = timeout(Duration::from_millis(10), rx).await {
+    println!("did not receive value within 10 ms");
+}
+

§Panics

+

This function panics if there is no current timer set.

+

It can be triggered when Builder::enable_time or +Builder::enable_all are not included in the builder.

+

It can also panic whenever a timer is created outside of a +Tokio runtime. That is why rt.block_on(sleep(...)) will panic, +since the function is executed outside of the runtime. +Whereas rt.block_on(async {sleep(...).await}) doesn’t panic. +And this is because wrapping the function on an async makes it lazy, +and so gets executed inside the runtime successfully without +panicking.

+
\ No newline at end of file diff --git a/actix_rt/time/index.html b/actix_rt/time/index.html new file mode 100644 index 00000000..6aebd288 --- /dev/null +++ b/actix_rt/time/index.html @@ -0,0 +1,9 @@ +actix_rt::time - Rust
actix_rt

Module time

source
Expand description

Utilities for tracking time (Tokio re-exports).

+

Structs§

Functions§

  • Creates new Interval that yields with interval of period. The first +tick completes immediately. The default [MissedTickBehavior] is +Burst, but this can be configured +by calling set_missed_tick_behavior.
  • Creates new Interval that yields with interval of period with the +first tick completing at start. The default [MissedTickBehavior] is +Burst, but this can be configured +by calling set_missed_tick_behavior.
  • Waits until duration has elapsed.
  • Waits until deadline is reached.
  • Requires a Future to complete before the specified duration has elapsed.
\ No newline at end of file diff --git a/actix_rt/time/sidebar-items.js b/actix_rt/time/sidebar-items.js new file mode 100644 index 00000000..414553ba --- /dev/null +++ b/actix_rt/time/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["interval","interval_at","sleep","sleep_until","timeout"],"struct":["Instant","Interval","Sleep","Timeout"]}; \ No newline at end of file diff --git a/actix_rt/time/struct.Instant.html b/actix_rt/time/struct.Instant.html new file mode 100644 index 00000000..415c48b5 --- /dev/null +++ b/actix_rt/time/struct.Instant.html @@ -0,0 +1,96 @@ +Instant in actix_rt::time - Rust
actix_rt::time

Struct Instant

pub struct Instant { /* private fields */ }
Expand description

A measurement of a monotonically nondecreasing clock. +Opaque and useful only with Duration.

+

Instants are always guaranteed to be no less than any previously measured +instant when created, and are often useful for tasks such as measuring +benchmarks or timing how long an operation takes.

+

Note, however, that instants are not guaranteed to be steady. In other +words, each tick of the underlying clock may not be the same length (e.g. +some seconds may be longer than others). An instant may jump forwards or +experience time dilation (slow down or speed up), but it will never go +backwards.

+

Instants are opaque types that can only be compared to one another. There is +no method to get “the number of seconds” from an instant. Instead, it only +allows measuring the duration between two instants (or comparing two +instants).

+

The size of an Instant struct may vary depending on the target operating +system.

+

§Note

+

This type wraps the inner std variant and is used to align the Tokio +clock for uses of now(). This can be useful for testing where you can +take advantage of time::pause() and time::advance().

+

Implementations§

§

impl Instant

pub fn now() -> Instant

Returns an instant corresponding to “now”.

+
§Examples
+
use tokio::time::Instant;
+
+let now = Instant::now();
+

pub fn from_std(std: Instant) -> Instant

Create a tokio::time::Instant from a std::time::Instant.

+

pub fn into_std(self) -> Instant

Convert the value into a std::time::Instant.

+

pub fn duration_since(&self, earlier: Instant) -> Duration

Returns the amount of time elapsed from another instant to this one, or +zero duration if that instant is later than this one.

+

pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration>

Returns the amount of time elapsed from another instant to this one, or +None if that instant is later than this one.

+
§Examples
+
use tokio::time::{Duration, Instant, sleep};
+
+#[tokio::main]
+async fn main() {
+    let now = Instant::now();
+    sleep(Duration::new(1, 0)).await;
+    let new_now = Instant::now();
+    println!("{:?}", new_now.checked_duration_since(now));
+    println!("{:?}", now.checked_duration_since(new_now)); // None
+}
+

pub fn saturating_duration_since(&self, earlier: Instant) -> Duration

Returns the amount of time elapsed from another instant to this one, or +zero duration if that instant is later than this one.

+
§Examples
+
use tokio::time::{Duration, Instant, sleep};
+
+#[tokio::main]
+async fn main() {
+    let now = Instant::now();
+    sleep(Duration::new(1, 0)).await;
+    let new_now = Instant::now();
+    println!("{:?}", new_now.saturating_duration_since(now));
+    println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
+}
+

pub fn elapsed(&self) -> Duration

Returns the amount of time elapsed since this instant was created, +or zero duration if that this instant is in the future.

+
§Examples
+
use tokio::time::{Duration, Instant, sleep};
+
+#[tokio::main]
+async fn main() {
+    let instant = Instant::now();
+    let three_secs = Duration::from_secs(3);
+    sleep(three_secs).await;
+    assert!(instant.elapsed() >= three_secs);
+}
+

pub fn checked_add(&self, duration: Duration) -> Option<Instant>

Returns Some(t) where t is the time self + duration if t can be +represented as Instant (which means it’s inside the bounds of the +underlying data structure), None otherwise.

+

pub fn checked_sub(&self, duration: Duration) -> Option<Instant>

Returns Some(t) where t is the time self - duration if t can be +represented as Instant (which means it’s inside the bounds of the +underlying data structure), None otherwise.

+

Trait Implementations§

§

impl Add<Duration> for Instant

§

type Output = Instant

The resulting type after applying the + operator.
§

fn add(self, other: Duration) -> Instant

Performs the + operation. Read more
§

impl AddAssign<Duration> for Instant

§

fn add_assign(&mut self, rhs: Duration)

Performs the += operation. Read more
§

impl Clone for Instant

§

fn clone(&self) -> Instant

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for Instant

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl From<Instant> for Instant

§

fn from(time: Instant) -> Instant

Converts to this type from the input type.
§

impl Hash for Instant

§

fn hash<__H>(&self, state: &mut __H)
where + __H: Hasher,

Feeds this value into the given Hasher. Read more
1.6.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + H: Hasher, + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
§

impl Ord for Instant

§

fn cmp(&self, other: &Instant) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized,

Restrict a value to a certain interval. Read more
§

impl PartialEq for Instant

§

fn eq(&self, other: &Instant) -> bool

Tests for self and other values to be equal, and is used by ==.
1.6.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
§

impl PartialOrd for Instant

§

fn partial_cmp(&self, other: &Instant) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.6.0 · source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.6.0 · source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the +<= operator. Read more
1.6.0 · source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > +operator. Read more
1.6.0 · source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by +the >= operator. Read more
§

impl Sub<Duration> for Instant

§

type Output = Instant

The resulting type after applying the - operator.
§

fn sub(self, rhs: Duration) -> Instant

Performs the - operation. Read more
§

impl Sub for Instant

§

type Output = Duration

The resulting type after applying the - operator.
§

fn sub(self, rhs: Instant) -> Duration

Performs the - operation. Read more
§

impl SubAssign<Duration> for Instant

§

fn sub_assign(&mut self, rhs: Duration)

Performs the -= operation. Read more
§

impl Copy for Instant

§

impl Eq for Instant

§

impl StructuralPartialEq for Instant

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/time/struct.Interval.html b/actix_rt/time/struct.Interval.html new file mode 100644 index 00000000..16e27f24 --- /dev/null +++ b/actix_rt/time/struct.Interval.html @@ -0,0 +1,144 @@ +Interval in actix_rt::time - Rust
actix_rt::time

Struct Interval

pub struct Interval { /* private fields */ }
Expand description

Interval returned by interval and interval_at.

+

This type allows you to wait on a sequence of instants with a certain +duration between each instant. Unlike calling sleep in a loop, this lets +you count the time spent between the calls to sleep as well.

+

An Interval can be turned into a Stream with IntervalStream.

+

Implementations§

§

impl Interval

pub async fn tick(&mut self) -> Instant

Completes when the next instant in the interval has been reached.

+
§Cancel safety
+

This method is cancellation safe. If tick is used as the branch in a tokio::select! and +another branch completes first, then no tick has been consumed.

+
§Examples
+
use tokio::time;
+
+use std::time::Duration;
+
+#[tokio::main]
+async fn main() {
+    let mut interval = time::interval(Duration::from_millis(10));
+
+    interval.tick().await;
+    // approximately 0ms have elapsed. The first tick completes immediately.
+    interval.tick().await;
+    interval.tick().await;
+
+    // approximately 20ms have elapsed.
+}
+

pub fn poll_tick(&mut self, cx: &mut Context<'_>) -> Poll<Instant>

Polls for the next instant in the interval to be reached.

+

This method can return the following values:

+
    +
  • Poll::Pending if the next instant has not yet been reached.
  • +
  • Poll::Ready(instant) if the next instant has been reached.
  • +
+

When this method returns Poll::Pending, the current task is scheduled +to receive a wakeup when the instant has elapsed. Note that on multiple +calls to poll_tick, only the Waker from the +Context passed to the most recent call is scheduled to receive a +wakeup.

+

pub fn reset(&mut self)

Resets the interval to complete one period after the current time.

+

This method ignores [MissedTickBehavior] strategy.

+

This is equivalent to calling reset_at(Instant::now() + period).

+
§Examples
+
use tokio::time;
+
+use std::time::Duration;
+
+#[tokio::main]
+async fn main() {
+    let mut interval = time::interval(Duration::from_millis(100));
+
+    interval.tick().await;
+
+    time::sleep(Duration::from_millis(50)).await;
+    interval.reset();
+
+    interval.tick().await;
+    interval.tick().await;
+
+    // approximately 250ms have elapsed.
+}
+

pub fn reset_immediately(&mut self)

Resets the interval immediately.

+

This method ignores [MissedTickBehavior] strategy.

+

This is equivalent to calling reset_at(Instant::now()).

+
§Examples
+
use tokio::time;
+
+use std::time::Duration;
+
+#[tokio::main]
+async fn main() {
+    let mut interval = time::interval(Duration::from_millis(100));
+
+    interval.tick().await;
+
+    time::sleep(Duration::from_millis(50)).await;
+    interval.reset_immediately();
+
+    interval.tick().await;
+    interval.tick().await;
+
+    // approximately 150ms have elapsed.
+}
+

pub fn reset_after(&mut self, after: Duration)

Resets the interval after the specified std::time::Duration.

+

This method ignores [MissedTickBehavior] strategy.

+

This is equivalent to calling reset_at(Instant::now() + after).

+
§Examples
+
use tokio::time;
+
+use std::time::Duration;
+
+#[tokio::main]
+async fn main() {
+    let mut interval = time::interval(Duration::from_millis(100));
+    interval.tick().await;
+
+    time::sleep(Duration::from_millis(50)).await;
+
+    let after = Duration::from_millis(20);
+    interval.reset_after(after);
+
+    interval.tick().await;
+    interval.tick().await;
+
+    // approximately 170ms have elapsed.
+}
+

pub fn reset_at(&mut self, deadline: Instant)

Resets the interval to a crate::time::Instant deadline.

+

Sets the next tick to expire at the given instant. If the instant is in +the past, then the [MissedTickBehavior] strategy will be used to +catch up. If the instant is in the future, then the next tick will +complete at the given instant, even if that means that it will sleep for +longer than the duration of this Interval. If the Interval had +any missed ticks before calling this method, then those are discarded.

+
§Examples
+
use tokio::time::{self, Instant};
+
+use std::time::Duration;
+
+#[tokio::main]
+async fn main() {
+    let mut interval = time::interval(Duration::from_millis(100));
+    interval.tick().await;
+
+    time::sleep(Duration::from_millis(50)).await;
+
+    let deadline = Instant::now() + Duration::from_millis(30);
+    interval.reset_at(deadline);
+
+    interval.tick().await;
+    interval.tick().await;
+
+    // approximately 180ms have elapsed.
+}
+

pub fn missed_tick_behavior(&self) -> MissedTickBehavior

Returns the [MissedTickBehavior] strategy currently being used.

+

pub fn set_missed_tick_behavior(&mut self, behavior: MissedTickBehavior)

Sets the [MissedTickBehavior] strategy that should be used.

+

pub fn period(&self) -> Duration

Returns the period of the interval.

+

Trait Implementations§

§

impl Debug for Interval

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/time/struct.Sleep.html b/actix_rt/time/struct.Sleep.html new file mode 100644 index 00000000..49a921c0 --- /dev/null +++ b/actix_rt/time/struct.Sleep.html @@ -0,0 +1,152 @@ +Sleep in actix_rt::time - Rust
actix_rt::time

Struct Sleep

pub struct Sleep { /* private fields */ }
Expand description

Future returned by sleep and sleep_until.

+

This type does not implement the Unpin trait, which means that if you +use it with select! or by calling poll, you have to pin it first. +If you use it with .await, this does not apply.

+

§Examples

+

Wait 100ms and print “100 ms have elapsed”.

+ +
use tokio::time::{sleep, Duration};
+
+#[tokio::main]
+async fn main() {
+    sleep(Duration::from_millis(100)).await;
+    println!("100 ms have elapsed");
+}
+

Use with select!. Pinning the Sleep with tokio::pin! is +necessary when the same Sleep is selected on multiple times.

+ +
use tokio::time::{self, Duration, Instant};
+
+#[tokio::main]
+async fn main() {
+    let sleep = time::sleep(Duration::from_millis(10));
+    tokio::pin!(sleep);
+
+    loop {
+        tokio::select! {
+            () = &mut sleep => {
+                println!("timer elapsed");
+                sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
+            },
+        }
+    }
+}
+

Use in a struct with boxing. By pinning the Sleep with a Box, the +HasSleep struct implements Unpin, even though Sleep does not.

+ +
use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+use tokio::time::Sleep;
+
+struct HasSleep {
+    sleep: Pin<Box<Sleep>>,
+}
+
+impl Future for HasSleep {
+    type Output = ();
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+        self.sleep.as_mut().poll(cx)
+    }
+}
+

Use in a struct with pin projection. This method avoids the Box, but +the HasSleep struct will not be Unpin as a consequence.

+ +
use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+use tokio::time::Sleep;
+use pin_project_lite::pin_project;
+
+pin_project! {
+    struct HasSleep {
+        #[pin]
+        sleep: Sleep,
+    }
+}
+
+impl Future for HasSleep {
+    type Output = ();
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+        self.project().sleep.poll(cx)
+    }
+}
+

Implementations§

§

impl Sleep

pub fn deadline(&self) -> Instant

Returns the instant at which the future will complete.

+

pub fn is_elapsed(&self) -> bool

Returns true if Sleep has elapsed.

+

A Sleep instance is elapsed when the requested duration has elapsed.

+

pub fn reset(self: Pin<&mut Sleep>, deadline: Instant)

Resets the Sleep instance to a new deadline.

+

Calling this function allows changing the instant at which the Sleep +future completes without having to create new associated state.

+

This function can be called both before and after the future has +completed.

+

To call this method, you will usually combine the call with +Pin::as_mut, which lets you call the method without consuming the +Sleep itself.

+
§Example
+
use tokio::time::{Duration, Instant};
+
+let sleep = tokio::time::sleep(Duration::from_millis(10));
+tokio::pin!(sleep);
+
+sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
+

See also the top-level examples.

+

Trait Implementations§

§

impl Debug for Sleep

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Future for Sleep

§

type Output = ()

The type of value produced on completion.
§

fn poll( + self: Pin<&mut Sleep>, + cx: &mut Context<'_>, +) -> Poll<<Sleep as Future>::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

§

impl !Freeze for Sleep

§

impl !RefUnwindSafe for Sleep

§

impl Send for Sleep

§

impl Sync for Sleep

§

impl !UnwindSafe for Sleep

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> FutureExt for T
where + T: Future + ?Sized,

§

fn map<U, F>(self, f: F) -> Map<Self, F>
where + F: FnOnce(Self::Output) -> U, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn map_into<U>(self) -> MapInto<Self, U>
where + Self::Output: Into<U>, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
where + F: FnOnce(Self::Output) -> Fut, + Fut: Future, + Self: Sized,

Chain on a computation for when a future finished, passing the result of +the future to the provided closure f. Read more
§

fn left_future<B>(self) -> Either<Self, B>
where + B: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the left-hand variant +of that Either. Read more
§

fn right_future<A>(self) -> Either<A, Self>
where + A: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the right-hand variant +of that Either. Read more
§

fn into_stream(self) -> IntoStream<Self>
where + Self: Sized,

Convert this future into a single element stream. Read more
§

fn flatten(self) -> Flatten<Self>
where + Self::Output: Future, + Self: Sized,

Flatten the execution of this future when the output of this +future is itself another future. Read more
§

fn flatten_stream(self) -> FlattenStream<Self>
where + Self::Output: Stream, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is a stream. Read more
§

fn fuse(self) -> Fuse<Self>
where + Self: Sized,

Fuse a future such that poll will never again be called once it has +completed. This method can be used to turn any Future into a +FusedFuture. Read more
§

fn inspect<F>(self, f: F) -> Inspect<Self, F>
where + F: FnOnce(&Self::Output), + Self: Sized,

Do something with the output of a future before passing it on. Read more
§

fn catch_unwind(self) -> CatchUnwind<Self>
where + Self: Sized + UnwindSafe,

Catches unwinding panics while polling the future. Read more
§

fn shared(self) -> Shared<Self>
where + Self: Sized, + Self::Output: Clone,

Create a cloneable handle to this future where all handles will resolve +to the same result. Read more
§

fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
where + Self: Sized + Send + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>
where + Self: Sized + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn unit_error(self) -> UnitError<Self>
where + Self: Sized,

§

fn never_error(self) -> NeverError<Self>
where + Self: Sized,

§

fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
where + Self: Unpin,

A convenience for calling Future::poll on Unpin future types.
§

fn now_or_never(self) -> Option<Self::Output>
where + Self: Sized,

Evaluates and consumes the future, returning the resulting output if +the future is ready after the first call to Future::poll. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<F> IntoFuture for F
where + F: Future,

source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
source§

type IntoFuture = F

Which kind of future are we turning this into?
source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_rt/time/struct.Timeout.html b/actix_rt/time/struct.Timeout.html new file mode 100644 index 00000000..79a7fe7f --- /dev/null +++ b/actix_rt/time/struct.Timeout.html @@ -0,0 +1,114 @@ +Timeout in actix_rt::time - Rust
actix_rt::time

Struct Timeout

pub struct Timeout<T> { /* private fields */ }
Expand description

Future returned by timeout and timeout_at.

+

Implementations§

§

impl<T> Timeout<T>

pub fn get_ref(&self) -> &T

Gets a reference to the underlying value in this timeout.

+

pub fn get_mut(&mut self) -> &mut T

Gets a mutable reference to the underlying value in this timeout.

+

pub fn into_inner(self) -> T

Consumes this timeout, returning the underlying value.

+

Trait Implementations§

§

impl<T> Debug for Timeout<T>
where + T: Debug,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<T> Future for Timeout<T>
where + T: Future,

§

type Output = Result<<T as Future>::Output, Elapsed>

The type of value produced on completion.
§

fn poll( + self: Pin<&mut Timeout<T>>, + cx: &mut Context<'_>, +) -> Poll<<Timeout<T> as Future>::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
§

impl<'__pin, T> Unpin for Timeout<T>
where + __Origin<'__pin, T>: Unpin,

Auto Trait Implementations§

§

impl<T> !Freeze for Timeout<T>

§

impl<T> !RefUnwindSafe for Timeout<T>

§

impl<T> Send for Timeout<T>
where + T: Send,

§

impl<T> Sync for Timeout<T>
where + T: Sync,

§

impl<T> !UnwindSafe for Timeout<T>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> FutureExt for T
where + T: Future + ?Sized,

§

fn map<U, F>(self, f: F) -> Map<Self, F>
where + F: FnOnce(Self::Output) -> U, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn map_into<U>(self) -> MapInto<Self, U>
where + Self::Output: Into<U>, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
where + F: FnOnce(Self::Output) -> Fut, + Fut: Future, + Self: Sized,

Chain on a computation for when a future finished, passing the result of +the future to the provided closure f. Read more
§

fn left_future<B>(self) -> Either<Self, B>
where + B: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the left-hand variant +of that Either. Read more
§

fn right_future<A>(self) -> Either<A, Self>
where + A: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the right-hand variant +of that Either. Read more
§

fn into_stream(self) -> IntoStream<Self>
where + Self: Sized,

Convert this future into a single element stream. Read more
§

fn flatten(self) -> Flatten<Self>
where + Self::Output: Future, + Self: Sized,

Flatten the execution of this future when the output of this +future is itself another future. Read more
§

fn flatten_stream(self) -> FlattenStream<Self>
where + Self::Output: Stream, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is a stream. Read more
§

fn fuse(self) -> Fuse<Self>
where + Self: Sized,

Fuse a future such that poll will never again be called once it has +completed. This method can be used to turn any Future into a +FusedFuture. Read more
§

fn inspect<F>(self, f: F) -> Inspect<Self, F>
where + F: FnOnce(&Self::Output), + Self: Sized,

Do something with the output of a future before passing it on. Read more
§

fn catch_unwind(self) -> CatchUnwind<Self>
where + Self: Sized + UnwindSafe,

Catches unwinding panics while polling the future. Read more
§

fn shared(self) -> Shared<Self>
where + Self: Sized, + Self::Output: Clone,

Create a cloneable handle to this future where all handles will resolve +to the same result. Read more
§

fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
where + Self: Sized + Send + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>
where + Self: Sized + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn unit_error(self) -> UnitError<Self>
where + Self: Sized,

§

fn never_error(self) -> NeverError<Self>
where + Self: Sized,

§

fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
where + Self: Unpin,

A convenience for calling Future::poll on Unpin future types.
§

fn now_or_never(self) -> Option<Self::Output>
where + Self: Sized,

Evaluates and consumes the future, returning the resulting output if +the future is ready after the first call to Future::poll. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<F> IntoFuture for F
where + F: Future,

source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
source§

type IntoFuture = F

Which kind of future are we turning this into?
source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<F, T, E> TryFuture for F
where + F: Future<Output = Result<T, E>> + ?Sized,

§

type Ok = T

The type of successful values yielded by this future
§

type Error = E

The type of failures yielded by this future
§

fn try_poll( + self: Pin<&mut F>, + cx: &mut Context<'_>, +) -> Poll<<F as Future>::Output>

Poll this TryFuture as if it were a Future. Read more
§

impl<Fut> TryFutureExt for Fut
where + Fut: TryFuture + ?Sized,

§

fn map_ok<T, F>(self, f: F) -> MapOk<Self, F>
where + F: FnOnce(Self::Ok) -> T, + Self: Sized,

Maps this future’s success value to a different value. Read more
§

fn map_ok_or_else<T, E, F>(self, e: E, f: F) -> MapOkOrElse<Self, F, E>
where + F: FnOnce(Self::Ok) -> T, + E: FnOnce(Self::Error) -> T, + Self: Sized,

Maps this future’s success value to a different value, and permits for error handling resulting in the same type. Read more
§

fn map_err<E, F>(self, f: F) -> MapErr<Self, F>
where + F: FnOnce(Self::Error) -> E, + Self: Sized,

Maps this future’s error value to a different value. Read more
§

fn err_into<E>(self) -> ErrInto<Self, E>
where + Self: Sized, + Self::Error: Into<E>,

Maps this future’s Error to a new error type +using the Into trait. Read more
§

fn ok_into<U>(self) -> OkInto<Self, U>
where + Self: Sized, + Self::Ok: Into<U>,

Maps this future’s Ok to a new type +using the Into trait.
§

fn and_then<Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
where + F: FnOnce(Self::Ok) -> Fut, + Fut: TryFuture<Error = Self::Error>, + Self: Sized,

Executes another future after this one resolves successfully. The +success value is passed to a closure to create this subsequent future. Read more
§

fn or_else<Fut, F>(self, f: F) -> OrElse<Self, Fut, F>
where + F: FnOnce(Self::Error) -> Fut, + Fut: TryFuture<Ok = Self::Ok>, + Self: Sized,

Executes another future if this one resolves to an error. The +error value is passed to a closure to create this subsequent future. Read more
§

fn inspect_ok<F>(self, f: F) -> InspectOk<Self, F>
where + F: FnOnce(&Self::Ok), + Self: Sized,

Do something with the success value of a future before passing it on. Read more
§

fn inspect_err<F>(self, f: F) -> InspectErr<Self, F>
where + F: FnOnce(&Self::Error), + Self: Sized,

Do something with the error value of a future before passing it on. Read more
§

fn try_flatten(self) -> TryFlatten<Self, Self::Ok>
where + Self::Ok: TryFuture<Error = Self::Error>, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is another future. Read more
§

fn try_flatten_stream(self) -> TryFlattenStream<Self>
where + Self::Ok: TryStream<Error = Self::Error>, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is a stream. Read more
§

fn unwrap_or_else<F>(self, f: F) -> UnwrapOrElse<Self, F>
where + Self: Sized, + F: FnOnce(Self::Error) -> Self::Ok,

Unwraps this future’s output, producing a future with this future’s +Ok type as its +Output type. Read more
§

fn into_future(self) -> IntoFuture<Self>
where + Self: Sized,

Wraps a [TryFuture] into a type that implements +Future. Read more
§

fn try_poll_unpin( + &mut self, + cx: &mut Context<'_>, +) -> Poll<Result<Self::Ok, Self::Error>>
where + Self: Unpin,

A convenience method for calling [TryFuture::try_poll] on Unpin +future types.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_server/all.html b/actix_server/all.html new file mode 100644 index 00000000..898ca72e --- /dev/null +++ b/actix_server/all.html @@ -0,0 +1 @@ +List of all items in this crate
\ No newline at end of file diff --git a/actix_server/builder/enum.MpTcp.html b/actix_server/builder/enum.MpTcp.html new file mode 100644 index 00000000..517d5f33 --- /dev/null +++ b/actix_server/builder/enum.MpTcp.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_server/enum.MpTcp.html...

+ + + \ No newline at end of file diff --git a/actix_server/builder/struct.ServerBuilder.html b/actix_server/builder/struct.ServerBuilder.html new file mode 100644 index 00000000..177f40ba --- /dev/null +++ b/actix_server/builder/struct.ServerBuilder.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_server/struct.ServerBuilder.html...

+ + + \ No newline at end of file diff --git a/actix_server/enum.MpTcp.html b/actix_server/enum.MpTcp.html new file mode 100644 index 00000000..cdc28d71 --- /dev/null +++ b/actix_server/enum.MpTcp.html @@ -0,0 +1,29 @@ +MpTcp in actix_server - Rust
actix_server

Enum MpTcp

source
pub enum MpTcp {
+    Disabled,
+    TcpFallback,
+    NoFallback,
+}
Expand description

Multipath TCP (MPTCP) preference.

+

Currently only useful on Linux.

+

Also see ServerBuilder::mptcp().

+

Variants§

§

Disabled

MPTCP will not be used when binding sockets.

+
§

TcpFallback

MPTCP will be attempted when binding sockets. If errors occur, regular TCP will be +attempted, too.

+
§

NoFallback

MPTCP will be used when binding sockets (with no fallback).

+

Trait Implementations§

source§

impl Clone for MpTcp

source§

fn clone(&self) -> MpTcp

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for MpTcp

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for MpTcp

§

impl RefUnwindSafe for MpTcp

§

impl Send for MpTcp

§

impl Sync for MpTcp

§

impl Unpin for MpTcp

§

impl UnwindSafe for MpTcp

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_server/handle/struct.ServerHandle.html b/actix_server/handle/struct.ServerHandle.html new file mode 100644 index 00000000..e5732d0e --- /dev/null +++ b/actix_server/handle/struct.ServerHandle.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_server/struct.ServerHandle.html...

+ + + \ No newline at end of file diff --git a/actix_server/index.html b/actix_server/index.html new file mode 100644 index 00000000..f5ea0493 --- /dev/null +++ b/actix_server/index.html @@ -0,0 +1,2 @@ +actix_server - Rust

Crate actix_server

source
Expand description

General purpose TCP server.

+

Re-exports§

  • pub use self::service::ServerServiceFactory;

Structs§

Enums§

  • Multipath TCP (MPTCP) preference.
\ No newline at end of file diff --git a/actix_server/server/struct.Server.html b/actix_server/server/struct.Server.html new file mode 100644 index 00000000..05a75685 --- /dev/null +++ b/actix_server/server/struct.Server.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_server/struct.Server.html...

+ + + \ No newline at end of file diff --git a/actix_server/sidebar-items.js b/actix_server/sidebar-items.js new file mode 100644 index 00000000..9e69b2e9 --- /dev/null +++ b/actix_server/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["MpTcp"],"struct":["Server","ServerBuilder","ServerHandle","TestServer"]}; \ No newline at end of file diff --git a/actix_server/struct.Server.html b/actix_server/struct.Server.html new file mode 100644 index 00000000..da62a72e --- /dev/null +++ b/actix_server/struct.Server.html @@ -0,0 +1,169 @@ +Server in actix_server - Rust
actix_server

Struct Server

source
pub struct Server { /* private fields */ }
Expand description

General purpose TCP server that runs services receiving Tokio TcpStreams.

+

Handles creating worker threads, restarting faulted workers, connection accepting, and +back-pressure logic.

+

Creates a worker per CPU core (or the number specified in ServerBuilder::workers) and +distributes connections with a round-robin strategy.

+

The Server must be awaited or polled in order to start running. It will resolve when the +server has fully shut down.

+

§Shutdown Signals

+

On UNIX systems, SIGTERM will start a graceful shutdown and SIGQUIT or SIGINT will start a +forced shutdown. On Windows, a Ctrl-C signal will start a forced shutdown.

+

A graceful shutdown will wait for all workers to stop first.

+

§Examples

+

The following is a TCP echo server. Test using telnet 127.0.0.1 8080.

+ +
use std::io;
+
+use actix_rt::net::TcpStream;
+use actix_server::Server;
+use actix_service::{fn_service, ServiceFactoryExt as _};
+use bytes::BytesMut;
+use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
+
+#[actix_rt::main]
+async fn main() -> io::Result<()> {
+    let bind_addr = ("127.0.0.1", 8080);
+
+    Server::build()
+        .bind("echo", bind_addr, move || {
+            fn_service(move |mut stream: TcpStream| {
+                async move {
+                    let mut size = 0;
+                    let mut buf = BytesMut::new();
+
+                    loop {
+                        match stream.read_buf(&mut buf).await {
+                            // end of stream; bail from loop
+                            Ok(0) => break,
+
+                            // write bytes back to stream
+                            Ok(bytes_read) => {
+                                stream.write_all(&buf[size..]).await.unwrap();
+                                size += bytes_read;
+                            }
+
+                            Err(err) => {
+                                eprintln!("Stream Error: {:?}", err);
+                                return Err(());
+                            }
+                        }
+                    }
+
+                    Ok(())
+                }
+            })
+            .map_err(|err| eprintln!("Service Error: {:?}", err))
+        })?
+        .run()
+        .await
+}
+

Implementations§

source§

impl Server

source

pub fn build() -> ServerBuilder

Create server build.

+
source

pub fn handle(&self) -> ServerHandle

Get a Server handle that can be used issue commands and change it’s state.

+

See ServerHandle for usage.

+

Trait Implementations§

source§

impl Future for Server

source§

type Output = Result<(), Error>

The type of value produced on completion.
source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

§

impl Freeze for Server

§

impl !RefUnwindSafe for Server

§

impl Send for Server

§

impl !Sync for Server

§

impl Unpin for Server

§

impl !UnwindSafe for Server

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> FutureExt for T
where + T: Future + ?Sized,

§

fn map<U, F>(self, f: F) -> Map<Self, F>
where + F: FnOnce(Self::Output) -> U, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn map_into<U>(self) -> MapInto<Self, U>
where + Self::Output: Into<U>, + Self: Sized,

Map this future’s output to a different type, returning a new future of +the resulting type. Read more
§

fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
where + F: FnOnce(Self::Output) -> Fut, + Fut: Future, + Self: Sized,

Chain on a computation for when a future finished, passing the result of +the future to the provided closure f. Read more
§

fn left_future<B>(self) -> Either<Self, B>
where + B: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the left-hand variant +of that Either. Read more
§

fn right_future<A>(self) -> Either<A, Self>
where + A: Future<Output = Self::Output>, + Self: Sized,

Wrap this future in an Either future, making it the right-hand variant +of that Either. Read more
§

fn into_stream(self) -> IntoStream<Self>
where + Self: Sized,

Convert this future into a single element stream. Read more
§

fn flatten(self) -> Flatten<Self>
where + Self::Output: Future, + Self: Sized,

Flatten the execution of this future when the output of this +future is itself another future. Read more
§

fn flatten_stream(self) -> FlattenStream<Self>
where + Self::Output: Stream, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is a stream. Read more
§

fn fuse(self) -> Fuse<Self>
where + Self: Sized,

Fuse a future such that poll will never again be called once it has +completed. This method can be used to turn any Future into a +FusedFuture. Read more
§

fn inspect<F>(self, f: F) -> Inspect<Self, F>
where + F: FnOnce(&Self::Output), + Self: Sized,

Do something with the output of a future before passing it on. Read more
§

fn catch_unwind(self) -> CatchUnwind<Self>
where + Self: Sized + UnwindSafe,

Catches unwinding panics while polling the future. Read more
§

fn shared(self) -> Shared<Self>
where + Self: Sized, + Self::Output: Clone,

Create a cloneable handle to this future where all handles will resolve +to the same result. Read more
§

fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
where + Self: Sized + Send + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>
where + Self: Sized + 'a,

Wrap the future in a Box, pinning it. Read more
§

fn unit_error(self) -> UnitError<Self>
where + Self: Sized,

§

fn never_error(self) -> NeverError<Self>
where + Self: Sized,

§

fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
where + Self: Unpin,

A convenience for calling Future::poll on Unpin future types.
§

fn now_or_never(self) -> Option<Self::Output>
where + Self: Sized,

Evaluates and consumes the future, returning the resulting output if +the future is ready after the first call to Future::poll. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<F> IntoFuture for F
where + F: Future,

source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
source§

type IntoFuture = F

Which kind of future are we turning this into?
source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<F, T, E> TryFuture for F
where + F: Future<Output = Result<T, E>> + ?Sized,

§

type Ok = T

The type of successful values yielded by this future
§

type Error = E

The type of failures yielded by this future
§

fn try_poll( + self: Pin<&mut F>, + cx: &mut Context<'_>, +) -> Poll<<F as Future>::Output>

Poll this TryFuture as if it were a Future. Read more
§

impl<Fut> TryFutureExt for Fut
where + Fut: TryFuture + ?Sized,

§

fn map_ok<T, F>(self, f: F) -> MapOk<Self, F>
where + F: FnOnce(Self::Ok) -> T, + Self: Sized,

Maps this future’s success value to a different value. Read more
§

fn map_ok_or_else<T, E, F>(self, e: E, f: F) -> MapOkOrElse<Self, F, E>
where + F: FnOnce(Self::Ok) -> T, + E: FnOnce(Self::Error) -> T, + Self: Sized,

Maps this future’s success value to a different value, and permits for error handling resulting in the same type. Read more
§

fn map_err<E, F>(self, f: F) -> MapErr<Self, F>
where + F: FnOnce(Self::Error) -> E, + Self: Sized,

Maps this future’s error value to a different value. Read more
§

fn err_into<E>(self) -> ErrInto<Self, E>
where + Self: Sized, + Self::Error: Into<E>,

Maps this future’s Error to a new error type +using the Into trait. Read more
§

fn ok_into<U>(self) -> OkInto<Self, U>
where + Self: Sized, + Self::Ok: Into<U>,

Maps this future’s Ok to a new type +using the Into trait.
§

fn and_then<Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
where + F: FnOnce(Self::Ok) -> Fut, + Fut: TryFuture<Error = Self::Error>, + Self: Sized,

Executes another future after this one resolves successfully. The +success value is passed to a closure to create this subsequent future. Read more
§

fn or_else<Fut, F>(self, f: F) -> OrElse<Self, Fut, F>
where + F: FnOnce(Self::Error) -> Fut, + Fut: TryFuture<Ok = Self::Ok>, + Self: Sized,

Executes another future if this one resolves to an error. The +error value is passed to a closure to create this subsequent future. Read more
§

fn inspect_ok<F>(self, f: F) -> InspectOk<Self, F>
where + F: FnOnce(&Self::Ok), + Self: Sized,

Do something with the success value of a future before passing it on. Read more
§

fn inspect_err<F>(self, f: F) -> InspectErr<Self, F>
where + F: FnOnce(&Self::Error), + Self: Sized,

Do something with the error value of a future before passing it on. Read more
§

fn try_flatten(self) -> TryFlatten<Self, Self::Ok>
where + Self::Ok: TryFuture<Error = Self::Error>, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is another future. Read more
§

fn try_flatten_stream(self) -> TryFlattenStream<Self>
where + Self::Ok: TryStream<Error = Self::Error>, + Self: Sized,

Flatten the execution of this future when the successful result of this +future is a stream. Read more
§

fn unwrap_or_else<F>(self, f: F) -> UnwrapOrElse<Self, F>
where + Self: Sized, + F: FnOnce(Self::Error) -> Self::Ok,

Unwraps this future’s output, producing a future with this future’s +Ok type as its +Output type. Read more
§

fn into_future(self) -> IntoFuture<Self>
where + Self: Sized,

Wraps a [TryFuture] into a type that implements +Future. Read more
§

fn try_poll_unpin( + &mut self, + cx: &mut Context<'_>, +) -> Poll<Result<Self::Ok, Self::Error>>
where + Self: Unpin,

A convenience method for calling [TryFuture::try_poll] on Unpin +future types.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_server/struct.ServerBuilder.html b/actix_server/struct.ServerBuilder.html new file mode 100644 index 00000000..13a180ff --- /dev/null +++ b/actix_server/struct.ServerBuilder.html @@ -0,0 +1,107 @@ +ServerBuilder in actix_server - Rust
actix_server

Struct ServerBuilder

source
pub struct ServerBuilder { /* private fields */ }
Expand description

Server builder.

+

Implementations§

source§

impl ServerBuilder

source

pub fn new() -> ServerBuilder

Create new Server builder instance

+
source

pub fn workers(self, num: usize) -> Self

Sets number of workers to start.

+

See bind() for more details on how worker count affects the number of +server factory instantiations.

+

The default worker count is the determined by std::thread::available_parallelism(). See +its documentation to determine what behavior you should expect when server is run.

+

num must be greater than 0.

+
§Panics
+

Panics if num is 0.

+
source

pub fn worker_max_blocking_threads(self, num: usize) -> Self

Set max number of threads for each worker’s blocking task thread pool.

+

One thread pool is set up per worker; not shared across workers.

+
§Examples:
+
let builder = ServerBuilder::new()
+    .workers(4) // server has 4 worker thread.
+    .worker_max_blocking_threads(4); // every worker has 4 max blocking threads.
+

See [tokio::runtime::Builder::max_blocking_threads] for behavior reference.

+
source

pub fn backlog(self, num: u32) -> Self

Set the maximum number of pending connections.

+

This refers to the number of clients that can be waiting to be served. Exceeding this number +results in the client getting an error when attempting to connect. It should only affect +servers under significant load.

+

Generally set in the 64-2048 range. Default value is 2048.

+

This method should be called before bind() method call.

+
source

pub fn mptcp(self, mptcp_enabled: MpTcp) -> Self

Sets MultiPath TCP (MPTCP) preference on bound sockets.

+

Multipath TCP (MPTCP) builds on top of TCP to improve connection redundancy and performance +by sharing a network data stream across multiple underlying TCP sessions. See mptcp.dev +for more info about MPTCP itself.

+

MPTCP is available on Linux kernel version 5.6 and higher. In addition, you’ll also need to +ensure the kernel option is enabled using sysctl net.mptcp.enabled=1.

+

This method will have no effect if called after a bind().

+
source

pub fn max_concurrent_connections(self, num: usize) -> Self

Sets the maximum per-worker number of concurrent connections.

+

All socket listeners will stop accepting connections when this limit is reached for +each worker.

+

By default max connections is set to a 25k per worker.

+
source

pub fn system_exit(self) -> Self

Sets flag to stop Actix System after server shutdown.

+

This has no effect when server is running in a Tokio-only runtime.

+
source

pub fn disable_signals(self) -> Self

Disables OS signal handling.

+
source

pub fn shutdown_timeout(self, sec: u64) -> Self

Timeout for graceful workers shutdown in seconds.

+

After receiving a stop signal, workers have this much time to finish serving requests. +Workers still alive after the timeout are force dropped.

+

By default shutdown timeout sets to 30 seconds.

+
source

pub fn bind<F, U, N>(self, name: N, addrs: U, factory: F) -> Result<Self>
where + F: ServerServiceFactory<TcpStream>, + U: ToSocketAddrs, + N: AsRef<str>,

Adds new service to the server.

+

Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.

+
§Worker Count
+

The factory will be instantiated multiple times in most scenarios. The number of +instantiations is number of workers × number of sockets resolved by +addrs.

+

For example, if you’ve manually set workers to 2, and use 127.0.0.1 +as the bind addrs, then factory will be instantiated twice. However, using localhost +as the bind addrs can often resolve to both 127.0.0.1 (IPv4) and ::1 (IPv6), causing +the factory to be instantiated 4 times (2 workers × 2 bind addresses).

+

Using a bind address of 0.0.0.0, which signals to use all interfaces, may also multiple +the number of instantiations in a similar way.

+
§Errors
+

Returns an io::Error if:

+
    +
  • addrs cannot be resolved into one or more socket addresses;
  • +
  • all the resolved socket addresses are already bound.
  • +
+
source

pub fn listen<F, N: AsRef<str>>( + self, + name: N, + lst: StdTcpListener, + factory: F, +) -> Result<Self>
where + F: ServerServiceFactory<TcpStream>,

Adds service to the server using a socket listener already bound.

+
§Worker Count
+

The factory will be instantiated multiple times in most scenarios. The number of +instantiations is: number of workers.

+
source

pub fn run(self) -> Server

Starts processing incoming connections and return server controller.

+
source§

impl ServerBuilder

source

pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> Result<Self>
where + F: ServerServiceFactory<UnixStream>, + N: AsRef<str>, + U: AsRef<Path>,

Adds new service to the server using a UDS (unix domain socket) address.

+
§Worker Count
+

The factory will be instantiated multiple times in most scenarios. The number of +instantiations is: number of workers.

+
source

pub fn listen_uds<F, N: AsRef<str>>( + self, + name: N, + lst: UnixListener, + factory: F, +) -> Result<Self>
where + F: ServerServiceFactory<UnixStream>,

Adds new service to the server using a UDS (unix domain socket) listener already bound.

+

Useful when running as a systemd service and a socket FD is acquired externally.

+
§Worker Count
+

The factory will be instantiated multiple times in most scenarios. The number of +instantiations is: number of workers.

+

Trait Implementations§

source§

impl Default for ServerBuilder

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_server/struct.ServerHandle.html b/actix_server/struct.ServerHandle.html new file mode 100644 index 00000000..97e20441 --- /dev/null +++ b/actix_server/struct.ServerHandle.html @@ -0,0 +1,23 @@ +ServerHandle in actix_server - Rust
actix_server

Struct ServerHandle

source
pub struct ServerHandle { /* private fields */ }
Expand description

Server handle.

+

Implementations§

source§

impl ServerHandle

source

pub fn pause(&self) -> impl Future<Output = ()>

Pause accepting incoming connections.

+

May drop socket pending connection. All open connections remain active.

+
source

pub fn resume(&self) -> impl Future<Output = ()>

Resume accepting incoming connections.

+
source

pub fn stop(&self, graceful: bool) -> impl Future<Output = ()>

Stop incoming connection processing, stop all workers and exit.

+

Trait Implementations§

source§

impl Clone for ServerHandle

source§

fn clone(&self) -> ServerHandle

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for ServerHandle

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_server/struct.TestServer.html b/actix_server/struct.TestServer.html new file mode 100644 index 00000000..d96f975f --- /dev/null +++ b/actix_server/struct.TestServer.html @@ -0,0 +1,40 @@ +TestServer in actix_server - Rust
actix_server

Struct TestServer

source
pub struct TestServer;
Expand description

A testing server.

+

TestServer is very simple test server that simplify process of writing integration tests for +network applications.

+

§Examples

+
use actix_service::fn_service;
+use actix_server::TestServer;
+
+#[actix_rt::main]
+async fn main() {
+    let srv = TestServer::start(|| fn_service(
+        |sock| async move {
+            println!("New connection: {:?}", sock);
+            Ok::<_, ()>(())
+        }
+    ));
+
+    println!("SOCKET: {:?}", srv.connect());
+}
+

Implementations§

source§

impl TestServer

source

pub fn start(factory: impl ServerServiceFactory<TcpStream>) -> TestServerHandle

Start new TestServer using application factory and default server config.

+
source

pub fn start_with_builder( + server_builder: ServerBuilder, + factory: impl ServerServiceFactory<TcpStream>, +) -> TestServerHandle

Start new TestServer using application factory and server builder.

+
source

pub fn unused_addr() -> SocketAddr

Get first available unused local address.

+

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_server/test_server/struct.TestServer.html b/actix_server/test_server/struct.TestServer.html new file mode 100644 index 00000000..08933b41 --- /dev/null +++ b/actix_server/test_server/struct.TestServer.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_server/struct.TestServer.html...

+ + + \ No newline at end of file diff --git a/actix_service/all.html b/actix_service/all.html new file mode 100644 index 00000000..78d293d8 --- /dev/null +++ b/actix_service/all.html @@ -0,0 +1 @@ +List of all items in this crate
\ No newline at end of file diff --git a/actix_service/apply/fn.apply_fn.html b/actix_service/apply/fn.apply_fn.html new file mode 100644 index 00000000..b2fdf29f --- /dev/null +++ b/actix_service/apply/fn.apply_fn.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.apply_fn.html...

+ + + \ No newline at end of file diff --git a/actix_service/apply/fn.apply_fn_factory.html b/actix_service/apply/fn.apply_fn_factory.html new file mode 100644 index 00000000..19abc6a5 --- /dev/null +++ b/actix_service/apply/fn.apply_fn_factory.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.apply_fn_factory.html...

+ + + \ No newline at end of file diff --git a/actix_service/apply_cfg/fn.apply_cfg.html b/actix_service/apply_cfg/fn.apply_cfg.html new file mode 100644 index 00000000..8844f540 --- /dev/null +++ b/actix_service/apply_cfg/fn.apply_cfg.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.apply_cfg.html...

+ + + \ No newline at end of file diff --git a/actix_service/apply_cfg/fn.apply_cfg_factory.html b/actix_service/apply_cfg/fn.apply_cfg_factory.html new file mode 100644 index 00000000..cf958335 --- /dev/null +++ b/actix_service/apply_cfg/fn.apply_cfg_factory.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.apply_cfg_factory.html...

+ + + \ No newline at end of file diff --git a/actix_service/boxed/fn.factory.html b/actix_service/boxed/fn.factory.html new file mode 100644 index 00000000..7f679365 --- /dev/null +++ b/actix_service/boxed/fn.factory.html @@ -0,0 +1,11 @@ +factory in actix_service::boxed - Rust
actix_service::boxed

Function factory

source
pub fn factory<SF, Req>(
+    factory: SF,
+) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error, SF::InitError>
where + SF: ServiceFactory<Req> + 'static, + Req: 'static, + SF::Response: 'static, + SF::Service: 'static, + SF::Future: 'static, + SF::Error: 'static, + SF::InitError: 'static,
Expand description

Wraps a service factory that returns service trait objects.

+
\ No newline at end of file diff --git a/actix_service/boxed/fn.rc_service.html b/actix_service/boxed/fn.rc_service.html new file mode 100644 index 00000000..8e5291b1 --- /dev/null +++ b/actix_service/boxed/fn.rc_service.html @@ -0,0 +1,5 @@ +rc_service in actix_service::boxed - Rust
actix_service::boxed

Function rc_service

source
pub fn rc_service<S, Req>(service: S) -> RcService<Req, S::Response, S::Error>
where + S: Service<Req> + 'static, + Req: 'static, + S::Future: 'static,
Expand description

Wraps service as a trait object using RcService.

+
\ No newline at end of file diff --git a/actix_service/boxed/fn.service.html b/actix_service/boxed/fn.service.html new file mode 100644 index 00000000..ac291d2c --- /dev/null +++ b/actix_service/boxed/fn.service.html @@ -0,0 +1,5 @@ +service in actix_service::boxed - Rust
actix_service::boxed

Function service

source
pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error>
where + S: Service<Req> + 'static, + Req: 'static, + S::Future: 'static,
Expand description

Wraps service as a trait object using BoxService.

+
\ No newline at end of file diff --git a/actix_service/boxed/index.html b/actix_service/boxed/index.html new file mode 100644 index 00000000..04a9601b --- /dev/null +++ b/actix_service/boxed/index.html @@ -0,0 +1,2 @@ +actix_service::boxed - Rust
actix_service

Module boxed

source
Expand description

Trait object forms of services and service factories.

+

Structs§

  • Wrapper for a service factory that will map it’s services to boxed trait object services.

Functions§

Type Aliases§

  • A boxed future with no send bound or lifetime parameters.
  • Type alias for service trait object using Box.
  • Type alias for service trait object using Rc.
\ No newline at end of file diff --git a/actix_service/boxed/sidebar-items.js b/actix_service/boxed/sidebar-items.js new file mode 100644 index 00000000..bec42849 --- /dev/null +++ b/actix_service/boxed/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["factory","rc_service","service"],"struct":["BoxServiceFactory"],"type":["BoxFuture","BoxService","RcService"]}; \ No newline at end of file diff --git a/actix_service/boxed/struct.BoxServiceFactory.html b/actix_service/boxed/struct.BoxServiceFactory.html new file mode 100644 index 00000000..30a8b60d --- /dev/null +++ b/actix_service/boxed/struct.BoxServiceFactory.html @@ -0,0 +1,29 @@ +BoxServiceFactory in actix_service::boxed - Rust
actix_service::boxed

Struct BoxServiceFactory

source
pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(/* private fields */);
Expand description

Wrapper for a service factory that will map it’s services to boxed trait object services.

+

Trait Implementations§

source§

impl<C, Req, Res, Err, InitErr> ServiceFactory<Req> for BoxServiceFactory<C, Req, Res, Err, InitErr>
where + Req: 'static, + Res: 'static, + Err: 'static, + InitErr: 'static,

source§

type Response = Res

Responses given by the created services.
source§

type Error = Err

Errors produced by the created services.
source§

type Config = C

Service factory configuration.
source§

type Service = Box<dyn Service<Req, Error = Err, Response = Res, Future = Pin<Box<dyn Future<Output = Result<Res, Err>>>>>>

The kind of Service created by this factory.
source§

type InitError = InitErr

Errors potentially raised while building a service.
source§

type Future = Pin<Box<dyn Future<Output = Result<<BoxServiceFactory<C, Req, Res, Err, InitErr> as ServiceFactory<Req>>::Service, InitErr>>>>

The future of the Service instance.g
source§

fn new_service(&self, cfg: C) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

§

impl<Cfg, Req, Res, Err, InitErr> Freeze for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>

§

impl<Cfg, Req, Res, Err, InitErr> !RefUnwindSafe for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>

§

impl<Cfg, Req, Res, Err, InitErr> !Send for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>

§

impl<Cfg, Req, Res, Err, InitErr> !Sync for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>

§

impl<Cfg, Req, Res, Err, InitErr> Unpin for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>

§

impl<Cfg, Req, Res, Err, InitErr> !UnwindSafe for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

source§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
source§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

source§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
source§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
source§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
source§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_service/boxed/type.BoxFuture.html b/actix_service/boxed/type.BoxFuture.html new file mode 100644 index 00000000..d232bc19 --- /dev/null +++ b/actix_service/boxed/type.BoxFuture.html @@ -0,0 +1,2 @@ +BoxFuture in actix_service::boxed - Rust
actix_service::boxed

Type Alias BoxFuture

source
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
Expand description

A boxed future with no send bound or lifetime parameters.

+

Aliased Type§

struct BoxFuture<T> {}
\ No newline at end of file diff --git a/actix_service/boxed/type.BoxService.html b/actix_service/boxed/type.BoxService.html new file mode 100644 index 00000000..8087330e --- /dev/null +++ b/actix_service/boxed/type.BoxService.html @@ -0,0 +1,2 @@ +BoxService in actix_service::boxed - Rust
actix_service::boxed

Type Alias BoxService

source
pub type BoxService<Req, Res, Err> = Box<dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>>;
Expand description

Type alias for service trait object using Box.

+

Aliased Type§

struct BoxService<Req, Res, Err>(/* private fields */);
\ No newline at end of file diff --git a/actix_service/boxed/type.RcService.html b/actix_service/boxed/type.RcService.html new file mode 100644 index 00000000..47528c9d --- /dev/null +++ b/actix_service/boxed/type.RcService.html @@ -0,0 +1,2 @@ +RcService in actix_service::boxed - Rust
actix_service::boxed

Type Alias RcService

source
pub type RcService<Req, Res, Err> = Rc<dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>>;
Expand description

Type alias for service trait object using Rc.

+

Aliased Type§

struct RcService<Req, Res, Err> { /* private fields */ }
\ No newline at end of file diff --git a/actix_service/ext/trait.ServiceExt.html b/actix_service/ext/trait.ServiceExt.html new file mode 100644 index 00000000..c214803a --- /dev/null +++ b/actix_service/ext/trait.ServiceExt.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/trait.ServiceExt.html...

+ + + \ No newline at end of file diff --git a/actix_service/ext/trait.ServiceFactoryExt.html b/actix_service/ext/trait.ServiceFactoryExt.html new file mode 100644 index 00000000..84e5329c --- /dev/null +++ b/actix_service/ext/trait.ServiceFactoryExt.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/trait.ServiceFactoryExt.html...

+ + + \ No newline at end of file diff --git a/actix_service/ext/trait.TransformExt.html b/actix_service/ext/trait.TransformExt.html new file mode 100644 index 00000000..a50c50ec --- /dev/null +++ b/actix_service/ext/trait.TransformExt.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/trait.TransformExt.html...

+ + + \ No newline at end of file diff --git a/actix_service/fn.apply.html b/actix_service/fn.apply.html new file mode 100644 index 00000000..bb2dcf4f --- /dev/null +++ b/actix_service/fn.apply.html @@ -0,0 +1,5 @@ +apply in actix_service - Rust
actix_service

Function apply

source
pub fn apply<T, S, I, Req>(t: T, factory: I) -> ApplyTransform<T, S, Req>
where + I: IntoServiceFactory<S, Req>, + S: ServiceFactory<Req>, + T: Transform<S::Service, Req, InitError = S::InitError>,
Expand description

Apply a Transform to a Service.

+
\ No newline at end of file diff --git a/actix_service/fn.apply_cfg.html b/actix_service/fn.apply_cfg.html new file mode 100644 index 00000000..de5c6c29 --- /dev/null +++ b/actix_service/fn.apply_cfg.html @@ -0,0 +1,9 @@ +apply_cfg in actix_service - Rust
actix_service

Function apply_cfg

source
pub fn apply_cfg<S1, Req, F, Cfg, Fut, S2, Err>(
+    srv: S1,
+    f: F,
+) -> impl ServiceFactory<Req, Config = Cfg, Response = S2::Response, Error = S2::Error, Service = S2, InitError = Err, Future = Fut> + Clone
where + S1: Service<Req>, + F: Fn(Cfg, &S1) -> Fut, + Fut: Future<Output = Result<S2, Err>>, + S2: Service<Req>,
Expand description

Convert Fn(Config, &Service1) -> Future<Service2> fn to a service factory.

+
\ No newline at end of file diff --git a/actix_service/fn.apply_cfg_factory.html b/actix_service/fn.apply_cfg_factory.html new file mode 100644 index 00000000..8d928500 --- /dev/null +++ b/actix_service/fn.apply_cfg_factory.html @@ -0,0 +1,11 @@ +apply_cfg_factory in actix_service - Rust
actix_service

Function apply_cfg_factory

source
pub fn apply_cfg_factory<SF, Req, F, Cfg, Fut, S>(
+    factory: SF,
+    f: F,
+) -> impl ServiceFactory<Req, Config = Cfg, Response = S::Response, Error = S::Error, Service = S, InitError = SF::InitError> + Clone
where + SF: ServiceFactory<Req, Config = ()>, + F: Fn(Cfg, &SF::Service) -> Fut, + SF::InitError: From<SF::Error>, + Fut: Future<Output = Result<S, SF::InitError>>, + S: Service<Req>,
Expand description

Convert Fn(Config, &ServiceFactory1) -> Future<ServiceFactory2> fn to a service factory.

+

Service1 get constructed from T factory.

+
\ No newline at end of file diff --git a/actix_service/fn.apply_fn.html b/actix_service/fn.apply_fn.html new file mode 100644 index 00000000..fd045636 --- /dev/null +++ b/actix_service/fn.apply_fn.html @@ -0,0 +1,10 @@ +apply_fn in actix_service - Rust
actix_service

Function apply_fn

source
pub fn apply_fn<I, S, F, Fut, Req, In, Res, Err>(
+    service: I,
+    wrap_fn: F,
+) -> Apply<S, F, Req, In, Res, Err>
where + I: IntoService<S, In>, + S: Service<In, Error = Err>, + F: Fn(Req, &S) -> Fut, + Fut: Future<Output = Result<Res, Err>>,
Expand description

Apply transform function to a service.

+

The In and Out type params refer to the request and response types for the wrapped service.

+
\ No newline at end of file diff --git a/actix_service/fn.apply_fn_factory.html b/actix_service/fn.apply_fn_factory.html new file mode 100644 index 00000000..70bc8d61 --- /dev/null +++ b/actix_service/fn.apply_fn_factory.html @@ -0,0 +1,10 @@ +apply_fn_factory in actix_service - Rust
actix_service

Function apply_fn_factory

source
pub fn apply_fn_factory<I, SF, F, Fut, Req, In, Res, Err>(
+    service: I,
+    f: F,
+) -> ApplyFactory<SF, F, Req, In, Res, Err>
where + I: IntoServiceFactory<SF, In>, + SF: ServiceFactory<In, Error = Err>, + F: Fn(Req, &SF::Service) -> Fut + Clone, + Fut: Future<Output = Result<Res, Err>>,
Expand description

Service factory that produces apply_fn service.

+

The In and Out type params refer to the request and response types for the wrapped service.

+
\ No newline at end of file diff --git a/actix_service/fn.fn_factory.html b/actix_service/fn.fn_factory.html new file mode 100644 index 00000000..3189b093 --- /dev/null +++ b/actix_service/fn.fn_factory.html @@ -0,0 +1,38 @@ +fn_factory in actix_service - Rust
actix_service

Function fn_factory

source
pub fn fn_factory<F, Cfg, Srv, Req, Fut, Err>(
+    f: F,
+) -> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
where + F: Fn() -> Fut, + Fut: Future<Output = Result<Srv, Err>>, + Srv: Service<Req>,
Expand description

Create ServiceFactory for function that can produce services

+

§Examples

+
use std::io;
+use actix_service::{fn_factory, fn_service, Service, ServiceFactory};
+use futures_util::future::ok;
+
+/// Service that divides two usize values.
+async fn div((x, y): (usize, usize)) -> Result<usize, io::Error> {
+    if y == 0 {
+        Err(io::Error::new(io::ErrorKind::Other, "divide by zero"))
+    } else {
+        Ok(x / y)
+    }
+}
+
+#[actix_rt::main]
+async fn main() -> io::Result<()> {
+    // Create service factory that produces `div` services
+    let factory = fn_factory(|| {
+        ok::<_, io::Error>(fn_service(div))
+    });
+
+    // construct new service
+    let srv = factory.new_service(()).await?;
+
+    // now we can use `div` service
+    let result = srv.call((10, 20)).await?;
+
+    println!("10 / 20 = {}", result);
+
+    Ok(())
+}
+
\ No newline at end of file diff --git a/actix_service/fn.fn_factory_with_config.html b/actix_service/fn.fn_factory_with_config.html new file mode 100644 index 00000000..2c5a196b --- /dev/null +++ b/actix_service/fn.fn_factory_with_config.html @@ -0,0 +1,31 @@ +fn_factory_with_config in actix_service - Rust
actix_service

Function fn_factory_with_config

source
pub fn fn_factory_with_config<F, Fut, Cfg, Srv, Req, Err>(
+    f: F,
+) -> FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
where + F: Fn(Cfg) -> Fut, + Fut: Future<Output = Result<Srv, Err>>, + Srv: Service<Req>,
Expand description

Create ServiceFactory for function that accepts config argument and can produce services

+

Any function that has following form Fn(Config) -> Future<Output = Service> could act as +a ServiceFactory.

+

§Examples

+
use std::io;
+use actix_service::{fn_factory_with_config, fn_service, Service, ServiceFactory};
+use futures_util::future::ok;
+
+#[actix_rt::main]
+async fn main() -> io::Result<()> {
+    // Create service factory. factory uses config argument for
+    // services it generates.
+    let factory = fn_factory_with_config(|y: usize| {
+        ok::<_, io::Error>(fn_service(move |x: usize| ok::<_, io::Error>(x * y)))
+    });
+
+    // construct new service with config argument
+    let srv = factory.new_service(10).await?;
+
+    let result = srv.call(10).await?;
+    assert_eq!(result, 100);
+
+    println!("10 * 10 = {}", result);
+    Ok(())
+}
+
\ No newline at end of file diff --git a/actix_service/fn.fn_service.html b/actix_service/fn.fn_service.html new file mode 100644 index 00000000..8a612809 --- /dev/null +++ b/actix_service/fn.fn_service.html @@ -0,0 +1,6 @@ +fn_service in actix_service - Rust
actix_service

Function fn_service

source
pub fn fn_service<F, Fut, Req, Res, Err, Cfg>(
+    f: F,
+) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
where + F: Fn(Req) -> Fut + Clone, + Fut: Future<Output = Result<Res, Err>>,
Expand description

Create ServiceFactory for function that can act as a Service

+
\ No newline at end of file diff --git a/actix_service/fn.into_service.html b/actix_service/fn.into_service.html new file mode 100644 index 00000000..95a6009a --- /dev/null +++ b/actix_service/fn.into_service.html @@ -0,0 +1,4 @@ +into_service in actix_service - Rust
actix_service

Function into_service

source
pub fn into_service<I, S, Req>(tp: I) -> S
where + I: IntoService<S, Req>, + S: Service<Req>,
Expand description

Convert object of type U to a service S

+
\ No newline at end of file diff --git a/actix_service/fn.map_config.html b/actix_service/fn.map_config.html new file mode 100644 index 00000000..dc62caf8 --- /dev/null +++ b/actix_service/fn.map_config.html @@ -0,0 +1,10 @@ +map_config in actix_service - Rust
actix_service

Function map_config

source
pub fn map_config<I, SF, Req, F, Cfg>(
+    factory: I,
+    f: F,
+) -> MapConfig<SF, Req, F, Cfg>
where + I: IntoServiceFactory<SF, Req>, + SF: ServiceFactory<Req>, + F: Fn(Cfg) -> SF::Config,
Expand description

Adapt external config argument to a config for provided service factory

+

Note that this function consumes the receiving service factory and returns +a wrapped version of it.

+
\ No newline at end of file diff --git a/actix_service/fn.unit_config.html b/actix_service/fn.unit_config.html new file mode 100644 index 00000000..68516d94 --- /dev/null +++ b/actix_service/fn.unit_config.html @@ -0,0 +1,4 @@ +unit_config in actix_service - Rust
actix_service

Function unit_config

source
pub fn unit_config<I, SF, Cfg, Req>(factory: I) -> UnitConfig<SF, Cfg, Req>
where + I: IntoServiceFactory<SF, Req>, + SF: ServiceFactory<Req, Config = ()>,
Expand description

Replace config with unit.

+
\ No newline at end of file diff --git a/actix_service/fn_service/fn.fn_factory.html b/actix_service/fn_service/fn.fn_factory.html new file mode 100644 index 00000000..d6973ed8 --- /dev/null +++ b/actix_service/fn_service/fn.fn_factory.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.fn_factory.html...

+ + + \ No newline at end of file diff --git a/actix_service/fn_service/fn.fn_factory_with_config.html b/actix_service/fn_service/fn.fn_factory_with_config.html new file mode 100644 index 00000000..e828658a --- /dev/null +++ b/actix_service/fn_service/fn.fn_factory_with_config.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.fn_factory_with_config.html...

+ + + \ No newline at end of file diff --git a/actix_service/fn_service/fn.fn_service.html b/actix_service/fn_service/fn.fn_service.html new file mode 100644 index 00000000..64dfab95 --- /dev/null +++ b/actix_service/fn_service/fn.fn_service.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.fn_service.html...

+ + + \ No newline at end of file diff --git a/actix_service/index.html b/actix_service/index.html new file mode 100644 index 00000000..bffcc68c --- /dev/null +++ b/actix_service/index.html @@ -0,0 +1,3 @@ +actix_service - Rust

Crate actix_service

source
Expand description

See Service docs for information on this crate’s foundational trait.

+

Modules§

  • Trait object forms of services and service factories.

Macros§

Structs§

Traits§

Functions§

  • Apply a Transform to a Service.
  • Convert Fn(Config, &Service1) -> Future<Service2> fn to a service factory.
  • Convert Fn(Config, &ServiceFactory1) -> Future<ServiceFactory2> fn to a service factory.
  • Apply transform function to a service.
  • Service factory that produces apply_fn service.
  • Create ServiceFactory for function that can produce services
  • Create ServiceFactory for function that accepts config argument and can produce services
  • Create ServiceFactory for function that can act as a Service
  • Convert object of type U to a service S
  • Adapt external config argument to a config for provided service factory
  • Replace config with unit.
\ No newline at end of file diff --git a/actix_service/macro.always_ready!.html b/actix_service/macro.always_ready!.html new file mode 100644 index 00000000..115b940a --- /dev/null +++ b/actix_service/macro.always_ready!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.always_ready.html...

+ + + \ No newline at end of file diff --git a/actix_service/macro.always_ready.html b/actix_service/macro.always_ready.html new file mode 100644 index 00000000..d9811daf --- /dev/null +++ b/actix_service/macro.always_ready.html @@ -0,0 +1,24 @@ +always_ready in actix_service - Rust
actix_service

Macro always_ready

source
macro_rules! always_ready {
+    () => { ... };
+}
Expand description

An implementation of poll_ready that always signals readiness.

+

This should only be used for basic leaf services that have no concept of un-readiness. +For wrapper or other service types, use forward_ready! for simple cases or write a bespoke +poll_ready implementation.

+

§Examples

+
use actix_service::Service;
+use futures_util::future::{ready, Ready};
+
+struct IdentityService;
+
+impl Service<u32> for IdentityService {
+    type Response = u32;
+    type Error = ();
+    type Future = Ready<Result<Self::Response, Self::Error>>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, req: u32) -> Self::Future {
+        ready(Ok(req))
+    }
+}
+
\ No newline at end of file diff --git a/actix_service/macro.forward_ready!.html b/actix_service/macro.forward_ready!.html new file mode 100644 index 00000000..e4ff6141 --- /dev/null +++ b/actix_service/macro.forward_ready!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.forward_ready.html...

+ + + \ No newline at end of file diff --git a/actix_service/macro.forward_ready.html b/actix_service/macro.forward_ready.html new file mode 100644 index 00000000..e91cad6c --- /dev/null +++ b/actix_service/macro.forward_ready.html @@ -0,0 +1,28 @@ +forward_ready in actix_service - Rust
actix_service

Macro forward_ready

source
macro_rules! forward_ready {
+    ($field:ident) => { ... };
+}
Expand description

An implementation of poll_ready that forwards readiness checks to a +named struct field.

+

Tuple structs are not supported.

+

§Examples

+
use actix_service::Service;
+use futures_util::future::{ready, Ready};
+
+struct WrapperService<S> {
+    inner: S,
+}
+
+impl<S> Service<()> for WrapperService<S>
+where
+    S: Service<()>,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = S::Future;
+
+    actix_service::forward_ready!(inner);
+
+    fn call(&self, req: ()) -> Self::Future {
+        self.inner.call(req)
+    }
+}
+
\ No newline at end of file diff --git a/actix_service/map_config/fn.map_config.html b/actix_service/map_config/fn.map_config.html new file mode 100644 index 00000000..dfc7e1f3 --- /dev/null +++ b/actix_service/map_config/fn.map_config.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.map_config.html...

+ + + \ No newline at end of file diff --git a/actix_service/map_config/fn.unit_config.html b/actix_service/map_config/fn.unit_config.html new file mode 100644 index 00000000..5e35d658 --- /dev/null +++ b/actix_service/map_config/fn.unit_config.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.unit_config.html...

+ + + \ No newline at end of file diff --git a/actix_service/sidebar-items.js b/actix_service/sidebar-items.js new file mode 100644 index 00000000..668241bb --- /dev/null +++ b/actix_service/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["apply","apply_cfg","apply_cfg_factory","apply_fn","apply_fn_factory","fn_factory","fn_factory_with_config","fn_service","into_service","map_config","unit_config"],"macro":["always_ready","forward_ready"],"mod":["boxed"],"struct":["ApplyTransform"],"trait":["IntoService","IntoServiceFactory","Service","ServiceExt","ServiceFactory","ServiceFactoryExt","Transform","TransformExt"]}; \ No newline at end of file diff --git a/actix_service/struct.ApplyTransform.html b/actix_service/struct.ApplyTransform.html new file mode 100644 index 00000000..45f785ff --- /dev/null +++ b/actix_service/struct.ApplyTransform.html @@ -0,0 +1,36 @@ +ApplyTransform in actix_service - Rust
actix_service

Struct ApplyTransform

source
pub struct ApplyTransform<T, S, Req>(/* private fields */);
Expand description

Apply a Transform to a Service.

+

Trait Implementations§

source§

impl<T, S, Req> Clone for ApplyTransform<T, S, Req>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T, S, Req> ServiceFactory<Req> for ApplyTransform<T, S, Req>
where + S: ServiceFactory<Req>, + T: Transform<S::Service, Req, InitError = S::InitError>,

source§

type Response = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::Response

Responses given by the created services.
source§

type Error = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::Error

Errors produced by the created services.
source§

type Config = <S as ServiceFactory<Req>>::Config

Service factory configuration.
source§

type Service = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::Transform

The kind of Service created by this factory.
source§

type InitError = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::InitError

Errors potentially raised while building a service.
source§

type Future = ApplyTransformFuture<T, S, Req>

The future of the Service instance.g
source§

fn new_service(&self, cfg: S::Config) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

§

impl<T, S, Req> Freeze for ApplyTransform<T, S, Req>

§

impl<T, S, Req> RefUnwindSafe for ApplyTransform<T, S, Req>
where + Req: RefUnwindSafe, + T: RefUnwindSafe, + S: RefUnwindSafe,

§

impl<T, S, Req> !Send for ApplyTransform<T, S, Req>

§

impl<T, S, Req> !Sync for ApplyTransform<T, S, Req>

§

impl<T, S, Req> Unpin for ApplyTransform<T, S, Req>
where + Req: Unpin,

§

impl<T, S, Req> UnwindSafe for ApplyTransform<T, S, Req>
where + Req: UnwindSafe, + T: RefUnwindSafe, + S: RefUnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

source§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
source§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

source§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
source§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
source§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
source§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_service/trait.IntoService.html b/actix_service/trait.IntoService.html new file mode 100644 index 00000000..79661b75 --- /dev/null +++ b/actix_service/trait.IntoService.html @@ -0,0 +1,8 @@ +IntoService in actix_service - Rust
actix_service

Trait IntoService

source
pub trait IntoService<S, Req>
where + S: Service<Req>,
{ + // Required method + fn into_service(self) -> S; +}
Expand description

Trait for types that can be converted to a Service

+

Required Methods§

source

fn into_service(self) -> S

Convert to a Service

+

Implementors§

source§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

\ No newline at end of file diff --git a/actix_service/trait.IntoServiceFactory.html b/actix_service/trait.IntoServiceFactory.html new file mode 100644 index 00000000..4ff1e067 --- /dev/null +++ b/actix_service/trait.IntoServiceFactory.html @@ -0,0 +1,8 @@ +IntoServiceFactory in actix_service - Rust
actix_service

Trait IntoServiceFactory

source
pub trait IntoServiceFactory<SF, Req>
where + SF: ServiceFactory<Req>,
{ + // Required method + fn into_factory(self) -> SF; +}
Expand description

Trait for types that can be converted to a ServiceFactory

+

Required Methods§

source

fn into_factory(self) -> SF

Convert Self to a ServiceFactory

+

Implementors§

source§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

\ No newline at end of file diff --git a/actix_service/trait.Service.html b/actix_service/trait.Service.html new file mode 100644 index 00000000..1f3b80d5 --- /dev/null +++ b/actix_service/trait.Service.html @@ -0,0 +1,71 @@ +Service in actix_service - Rust
actix_service

Trait Service

source
pub trait Service<Req> {
+    type Response;
+    type Error;
+    type Future: Future<Output = Result<Self::Response, Self::Error>>;
+
+    // Required methods
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
+    fn call(&self, req: Req) -> Self::Future;
+}
Expand description

An asynchronous operation from Request to a Response.

+

The Service trait models a request/response interaction, receiving requests and returning +replies. You can think about a service as a function with one argument that returns some result +asynchronously. Conceptually, the operation looks like this:

+ +
async fn(Request) -> Result<Response, Err>
+

The Service trait just generalizes this form. Requests are defined as a generic type parameter +and responses and other details are defined as associated types on the trait impl. Notice that +this design means that services can receive many request types and converge them to a single +response type.

+

Services can also have mutable state that influence computation by using a Cell, RefCell +or Mutex. Services intentionally do not take &mut self to reduce overhead in the +common cases.

+

Service provides a symmetric and uniform API; the same abstractions can be used to represent +both clients and servers. Services describe only transformation operations which encourage +simple API surfaces. This leads to simpler design of each service, improves test-ability and +makes composition easier.

+ +
struct MyService;
+
+impl Service<u8> for MyService {
+     type Response = u64;
+     type Error = MyError;
+     type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
+
+     fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { ... }
+
+     fn call(&self, req: u8) -> Self::Future { ... }
+}
+

Sometimes it is not necessary to implement the Service trait. For example, the above service +could be rewritten as a simple function and passed to fn_service.

+ +
async fn my_service(req: u8) -> Result<u64, MyError>;
+
+let svc = fn_service(my_service)
+svc.call(123)
+

Required Associated Types§

source

type Response

Responses given by the service.

+
source

type Error

Errors produced by the service when polling readiness or executing call.

+
source

type Future: Future<Output = Result<Self::Response, Self::Error>>

The future response value.

+

Required Methods§

source

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests.

+

If the service is at capacity, then Pending is returned and the task is notified when the +service becomes ready again. This function is expected to be called while on a task.

+

This is a best effort implementation. False positives are permitted. It is permitted for +the service to return Ready from a poll_ready call and the next invocation of call +results in an error.

+
§Notes
+
    +
  1. poll_ready might be called on a different task to call.
  2. +
  3. In cases of chained services, .poll_ready() is called for all services at once.
  4. +
+
source

fn call(&self, req: Req) -> Self::Future

Process the request and return the response asynchronously.

+

This function is expected to be callable off-task. As such, implementations of call should +take care to not call poll_ready. If the service is at capacity and the request is unable +to be handled, the returned Future should resolve to an error.

+

Invoking call without first invoking poll_ready is permitted. Implementations must be +resilient to this fact.

+

Implementations on Foreign Types§

source§

impl<'a, S, Req> Service<Req> for &'a S
where + S: Service<Req> + 'a,

source§

type Response = <S as Service<Req>>::Response

source§

type Error = <S as Service<Req>>::Error

source§

type Future = <S as Service<Req>>::Future

source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

source§

fn call(&self, request: Req) -> S::Future

source§

impl<'a, S, Req> Service<Req> for &'a mut S
where + S: Service<Req> + 'a,

source§

type Response = <S as Service<Req>>::Response

source§

type Error = <S as Service<Req>>::Error

source§

type Future = <S as Service<Req>>::Future

source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

source§

fn call(&self, request: Req) -> S::Future

source§

impl<S, Req> Service<Req> for Box<S>
where + S: Service<Req> + ?Sized,

source§

type Response = <S as Service<Req>>::Response

source§

type Error = <S as Service<Req>>::Error

source§

type Future = <S as Service<Req>>::Future

source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), S::Error>>

source§

fn call(&self, request: Req) -> S::Future

source§

impl<S, Req> Service<Req> for Rc<S>
where + S: Service<Req> + ?Sized,

source§

type Response = <S as Service<Req>>::Response

source§

type Error = <S as Service<Req>>::Error

source§

type Future = <S as Service<Req>>::Future

source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

source§

fn call(&self, request: Req) -> S::Future

source§

impl<S, Req> Service<Req> for RefCell<S>
where + S: Service<Req>,

This impl is deprecated since v2 because the Service trait now receives shared reference.

+
source§

type Response = <S as Service<Req>>::Response

source§

type Error = <S as Service<Req>>::Error

source§

type Future = <S as Service<Req>>::Future

source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

source§

fn call(&self, request: Req) -> S::Future

Implementors§

\ No newline at end of file diff --git a/actix_service/trait.ServiceExt.html b/actix_service/trait.ServiceExt.html new file mode 100644 index 00000000..34c1dafb --- /dev/null +++ b/actix_service/trait.ServiceExt.html @@ -0,0 +1,40 @@ +ServiceExt in actix_service - Rust
actix_service

Trait ServiceExt

source
pub trait ServiceExt<Req>: Service<Req> {
+    // Provided methods
+    fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
+       where Self: Sized,
+             F: FnMut(Self::Response) -> R { ... }
+    fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
+       where Self: Sized,
+             F: Fn(Self::Error) -> E { ... }
+    fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
+       where Self: Sized,
+             I: IntoService<S1, Self::Response>,
+             S1: Service<Self::Response, Error = Self::Error> { ... }
+}
Expand description

An extension trait for Services that provides a variety of convenient adapters.

+

Provided Methods§

source

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type.

+

This function is similar to the Option::map or Iterator::map where +it will change the type of the underlying service.

+

Note that this function consumes the receiving service and returns a +wrapped version of it, similar to the existing map methods in the +standard library.

+
source

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service.

+

This function is similar to the Result::map_err where it will change +the error type of the underlying service. For example, this can be useful to +ensure that services have the same error type.

+

Note that this function consumes the receiving service and returns a +wrapped version of it.

+
source

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully.

+

This function can be used to chain two services together and ensure that the second service +isn’t called until call to the first service have finished. Result of the call to the first +service is used as an input parameter for the second service’s call.

+

Note that this function consumes the receiving service and returns a wrapped version of it.

+

Implementors§

source§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

\ No newline at end of file diff --git a/actix_service/trait.ServiceFactory.html b/actix_service/trait.ServiceFactory.html new file mode 100644 index 00000000..4fcc0818 --- /dev/null +++ b/actix_service/trait.ServiceFactory.html @@ -0,0 +1,34 @@ +ServiceFactory in actix_service - Rust
actix_service

Trait ServiceFactory

source
pub trait ServiceFactory<Req> {
+    type Response;
+    type Error;
+    type Config;
+    type Service: Service<Req, Response = Self::Response, Error = Self::Error>;
+    type InitError;
+    type Future: Future<Output = Result<Self::Service, Self::InitError>>;
+
+    // Required method
+    fn new_service(&self, cfg: Self::Config) -> Self::Future;
+}
Expand description

Factory for creating Services.

+

This is useful for cases where new Services must be produced. One case is a TCP +server listener: a listener accepts new connections, constructs a new Service for each using +the ServiceFactory trait, and uses the new Service to process inbound requests on that new +connection.

+

Config is a service factory configuration type.

+

Simple factories may be able to use fn_factory or fn_factory_with_config to +reduce boilerplate.

+

Required Associated Types§

source

type Response

Responses given by the created services.

+
source

type Error

Errors produced by the created services.

+
source

type Config

Service factory configuration.

+
source

type Service: Service<Req, Response = Self::Response, Error = Self::Error>

The kind of Service created by this factory.

+
source

type InitError

Errors potentially raised while building a service.

+
source

type Future: Future<Output = Result<Self::Service, Self::InitError>>

The future of the Service instance.g

+

Required Methods§

source

fn new_service(&self, cfg: Self::Config) -> Self::Future

Create and return a new service asynchronously.

+

Implementations on Foreign Types§

source§

impl<S, Req> ServiceFactory<Req> for Rc<S>
where + S: ServiceFactory<Req>,

source§

impl<S, Req> ServiceFactory<Req> for Arc<S>
where + S: ServiceFactory<Req>,

Implementors§

source§

impl<C, Req, Res, Err, InitErr> ServiceFactory<Req> for BoxServiceFactory<C, Req, Res, Err, InitErr>
where + Req: 'static, + Res: 'static, + Err: 'static, + InitErr: 'static,

source§

type Response = Res

source§

type Error = Err

source§

type Config = C

source§

type Service = Box<dyn Service<Req, Error = Err, Response = Res, Future = Pin<Box<dyn Future<Output = Result<Res, Err>>>>>>

source§

type InitError = InitErr

source§

type Future = Pin<Box<dyn Future<Output = Result<<BoxServiceFactory<C, Req, Res, Err, InitErr> as ServiceFactory<Req>>::Service, InitErr>>>>

source§

impl<T, S, Req> ServiceFactory<Req> for ApplyTransform<T, S, Req>
where + S: ServiceFactory<Req>, + T: Transform<S::Service, Req, InitError = S::InitError>,

source§

type Response = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::Response

source§

type Error = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::Error

source§

type Config = <S as ServiceFactory<Req>>::Config

source§

type Service = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::Transform

source§

type InitError = <T as Transform<<S as ServiceFactory<Req>>::Service, Req>>::InitError

source§

type Future = ApplyTransformFuture<T, S, Req>

\ No newline at end of file diff --git a/actix_service/trait.ServiceFactoryExt.html b/actix_service/trait.ServiceFactoryExt.html new file mode 100644 index 00000000..4d14be4a --- /dev/null +++ b/actix_service/trait.ServiceFactoryExt.html @@ -0,0 +1,37 @@ +ServiceFactoryExt in actix_service - Rust
actix_service

Trait ServiceFactoryExt

source
pub trait ServiceFactoryExt<Req>: ServiceFactory<Req> {
+    // Provided methods
+    fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
+       where Self: Sized,
+             F: FnMut(Self::Response) -> R + Clone { ... }
+    fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
+       where Self: Sized,
+             F: Fn(Self::Error) -> E + Clone { ... }
+    fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
+       where Self: Sized,
+             F: Fn(Self::InitError) -> E + Clone { ... }
+    fn and_then<I, SF1>(
+        self,
+        factory: I,
+    ) -> AndThenServiceFactory<Self, SF1, Req>
+       where Self: Sized,
+             Self::Config: Clone,
+             I: IntoServiceFactory<SF1, Self::Response>,
+             SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError> { ... }
+}
Expand description

An extension trait for ServiceFactorys that provides a variety of convenient adapters.

+

Provided Methods§

source

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.

+
source

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.

+
source

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.

+
source

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.

+

Implementors§

source§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

\ No newline at end of file diff --git a/actix_service/trait.Transform.html b/actix_service/trait.Transform.html new file mode 100644 index 00000000..9eda089d --- /dev/null +++ b/actix_service/trait.Transform.html @@ -0,0 +1,68 @@ +Transform in actix_service - Rust
actix_service

Trait Transform

source
pub trait Transform<S, Req> {
+    type Response;
+    type Error;
+    type Transform: Service<Req, Response = Self::Response, Error = Self::Error>;
+    type InitError;
+    type Future: Future<Output = Result<Self::Transform, Self::InitError>>;
+
+    // Required method
+    fn new_transform(&self, service: S) -> Self::Future;
+}
Expand description

Defines the interface of a service factory that wraps inner service during construction.

+

Transformers wrap an inner service and runs during inbound and/or outbound processing in the +service lifecycle. It may modify request and/or response.

+

For example, a timeout service wrapper:

+ +
pub struct Timeout<S> {
+    service: S,
+    timeout: Duration,
+}
+
+impl<S: Service<Req>, Req> Service<Req> for Timeout<S> {
+    type Response = S::Response;
+    type Error = TimeoutError<S::Error>;
+    type Future = TimeoutServiceResponse<S>;
+
+    actix_service::forward_ready!(service);
+
+    fn call(&self, req: Req) -> Self::Future {
+        TimeoutServiceResponse {
+            fut: self.service.call(req),
+            sleep: Sleep::new(clock::now() + self.timeout),
+        }
+    }
+}
+

This wrapper service is decoupled from the underlying service implementation and could be +applied to any service.

+

The Transform trait defines the interface of a service wrapper. Transform is often +implemented for middleware, defining how to construct a middleware Service. A Service that is +constructed by the factory takes the Service that follows it during execution as a parameter, +assuming ownership of the next Service.

+

A transform for the Timeout middleware could look like this:

+ +
pub struct TimeoutTransform {
+    timeout: Duration,
+}
+
+impl<S: Service<Req>, Req> Transform<S, Req> for TimeoutTransform {
+    type Response = S::Response;
+    type Error = TimeoutError<S::Error>;
+    type InitError = S::Error;
+    type Transform = Timeout<S>;
+    type Future = Ready<Result<Self::Transform, Self::InitError>>;
+
+    fn new_transform(&self, service: S) -> Self::Future {
+        ready(Ok(Timeout {
+            service,
+            timeout: self.timeout,
+        }))
+    }
+}
+

Required Associated Types§

source

type Response

Responses produced by the service.

+
source

type Error

Errors produced by the service.

+
source

type Transform: Service<Req, Response = Self::Response, Error = Self::Error>

The TransformService value created by this factory

+
source

type InitError

Errors produced while building a transform service.

+
source

type Future: Future<Output = Result<Self::Transform, Self::InitError>>

The future response value.

+

Required Methods§

source

fn new_transform(&self, service: S) -> Self::Future

Creates and returns a new Transform component, asynchronously

+

Implementations on Foreign Types§

source§

impl<T, S, Req> Transform<S, Req> for Rc<T>
where + T: Transform<S, Req>,

source§

type Response = <T as Transform<S, Req>>::Response

source§

type Error = <T as Transform<S, Req>>::Error

source§

type Transform = <T as Transform<S, Req>>::Transform

source§

type InitError = <T as Transform<S, Req>>::InitError

source§

type Future = <T as Transform<S, Req>>::Future

source§

fn new_transform(&self, service: S) -> T::Future

source§

impl<T, S, Req> Transform<S, Req> for Arc<T>
where + T: Transform<S, Req>,

source§

type Response = <T as Transform<S, Req>>::Response

source§

type Error = <T as Transform<S, Req>>::Error

source§

type Transform = <T as Transform<S, Req>>::Transform

source§

type InitError = <T as Transform<S, Req>>::InitError

source§

type Future = <T as Transform<S, Req>>::Future

source§

fn new_transform(&self, service: S) -> T::Future

Implementors§

\ No newline at end of file diff --git a/actix_service/trait.TransformExt.html b/actix_service/trait.TransformExt.html new file mode 100644 index 00000000..36fbd6af --- /dev/null +++ b/actix_service/trait.TransformExt.html @@ -0,0 +1,11 @@ +TransformExt in actix_service - Rust
actix_service

Trait TransformExt

source
pub trait TransformExt<S, Req>: Transform<S, Req> {
+    // Provided method
+    fn map_init_err<F, E>(self, f: F) -> TransformMapInitErr<Self, S, Req, F, E>
+       where Self: Sized,
+             F: Fn(Self::InitError) -> E + Clone { ... }
+}
Expand description

An extension trait for Transforms that provides a variety of convenient adapters.

+

Provided Methods§

source

fn map_init_err<F, E>(self, f: F) -> TransformMapInitErr<Self, S, Req, F, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Return a new Transform whose init error is mapped to to a different type.

+

Implementors§

source§

impl<T, Req> TransformExt<T, Req> for T
where + T: Transform<T, Req>,

\ No newline at end of file diff --git a/actix_service/transform/fn.apply.html b/actix_service/transform/fn.apply.html new file mode 100644 index 00000000..d2820902 --- /dev/null +++ b/actix_service/transform/fn.apply.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/fn.apply.html...

+ + + \ No newline at end of file diff --git a/actix_service/transform/struct.ApplyTransform.html b/actix_service/transform/struct.ApplyTransform.html new file mode 100644 index 00000000..0b77d7d5 --- /dev/null +++ b/actix_service/transform/struct.ApplyTransform.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/struct.ApplyTransform.html...

+ + + \ No newline at end of file diff --git a/actix_service/transform/trait.Transform.html b/actix_service/transform/trait.Transform.html new file mode 100644 index 00000000..e5457e69 --- /dev/null +++ b/actix_service/transform/trait.Transform.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../actix_service/trait.Transform.html...

+ + + \ No newline at end of file diff --git a/actix_tls/accept/enum.TlsError.html b/actix_tls/accept/enum.TlsError.html new file mode 100644 index 00000000..71b11172 --- /dev/null +++ b/actix_tls/accept/enum.TlsError.html @@ -0,0 +1,45 @@ +TlsError in actix_tls::accept - Rust
actix_tls::accept

Enum TlsError

source
pub enum TlsError<TlsErr, SvcErr> {
+    Timeout,
+    Tls(TlsErr),
+    Service(SvcErr),
+}
Expand description

TLS handshake error, TLS timeout, or inner service error.

+

All TLS acceptors from this crate will return the SvcErr type parameter as Infallible, +which can be cast to your own service type, inferred or otherwise, using into_service_error.

+

Variants§

§

Timeout

TLS handshake has timed-out.

+
§

Tls(TlsErr)

Wraps TLS service errors.

+
§

Service(SvcErr)

Wraps service errors.

+

Implementations§

source§

impl<TlsErr> TlsError<TlsErr, Infallible>

source

pub fn into_service_error<SvcErr>(self) -> TlsError<TlsErr, SvcErr>

Casts the infallible service error type returned from acceptors into caller’s type.

+
§Examples
+
let a: TlsError<u32, Infallible> = TlsError::Tls(42);
+let _b: TlsError<u32, u64> = a.into_service_error();
+

Trait Implementations§

source§

impl<TlsErr: Debug, SvcErr: Debug> Debug for TlsError<TlsErr, SvcErr>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<TlsErr, SvcErr> Display for TlsError<TlsErr, SvcErr>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<TlsErr, SvcErr> Error for TlsError<TlsErr, SvcErr>
where + TlsErr: Error + 'static, + SvcErr: Error + 'static,

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more

Auto Trait Implementations§

§

impl<TlsErr, SvcErr> Freeze for TlsError<TlsErr, SvcErr>
where + TlsErr: Freeze, + SvcErr: Freeze,

§

impl<TlsErr, SvcErr> RefUnwindSafe for TlsError<TlsErr, SvcErr>
where + TlsErr: RefUnwindSafe, + SvcErr: RefUnwindSafe,

§

impl<TlsErr, SvcErr> Send for TlsError<TlsErr, SvcErr>
where + TlsErr: Send, + SvcErr: Send,

§

impl<TlsErr, SvcErr> Sync for TlsError<TlsErr, SvcErr>
where + TlsErr: Sync, + SvcErr: Sync,

§

impl<TlsErr, SvcErr> Unpin for TlsError<TlsErr, SvcErr>
where + TlsErr: Unpin, + SvcErr: Unpin,

§

impl<TlsErr, SvcErr> UnwindSafe for TlsError<TlsErr, SvcErr>
where + TlsErr: UnwindSafe, + SvcErr: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/fn.max_concurrent_tls_connect.html b/actix_tls/accept/fn.max_concurrent_tls_connect.html new file mode 100644 index 00000000..74644a2f --- /dev/null +++ b/actix_tls/accept/fn.max_concurrent_tls_connect.html @@ -0,0 +1,5 @@ +max_concurrent_tls_connect in actix_tls::accept - Rust
actix_tls::accept

Function max_concurrent_tls_connect

source
pub fn max_concurrent_tls_connect(num: usize)
Expand description

Sets the maximum per-worker concurrent TLS connection limit.

+

All listeners will stop accepting connections when this limit is reached. +It can be used to regulate the global TLS CPU usage.

+

By default, the connection limit is 256.

+
\ No newline at end of file diff --git a/actix_tls/accept/index.html b/actix_tls/accept/index.html new file mode 100644 index 00000000..ce2ae63e --- /dev/null +++ b/actix_tls/accept/index.html @@ -0,0 +1,2 @@ +actix_tls::accept - Rust
actix_tls

Module accept

source
Expand description

TLS connection acceptor services.

+

Modules§

  • native-tls based TLS connection acceptor service.
  • openssl based TLS acceptor service.
  • rustls v0.20 based TLS connection acceptor service.
  • rustls v0.21 based TLS connection acceptor service.
  • rustls v0.22 based TLS connection acceptor service.
  • rustls v0.23 based TLS connection acceptor service.

Enums§

  • TLS handshake error, TLS timeout, or inner service error.

Functions§

\ No newline at end of file diff --git a/actix_tls/accept/native_tls/index.html b/actix_tls/accept/native_tls/index.html new file mode 100644 index 00000000..0d13c452 --- /dev/null +++ b/actix_tls/accept/native_tls/index.html @@ -0,0 +1,3 @@ +actix_tls::accept::native_tls - Rust
actix_tls::accept

Module native_tls

source
Expand description

native-tls based TLS connection acceptor service.

+

See Acceptor for main service factory docs.

+

Modules§

  • Re-exports from native-tls that are useful for acceptors.

Structs§

  • Accept TLS connections via the native-tls crate.
  • Native-TLS based acceptor service.
  • Wraps a native-tls based async TLS stream in order to implement [ActixStream].
\ No newline at end of file diff --git a/actix_tls/accept/native_tls/reexports/index.html b/actix_tls/accept/native_tls/reexports/index.html new file mode 100644 index 00000000..7b600917 --- /dev/null +++ b/actix_tls/accept/native_tls/reexports/index.html @@ -0,0 +1,3 @@ +actix_tls::accept::native_tls::reexports - Rust
actix_tls::accept::native_tls

Module reexports

source
Expand description

Re-exports from native-tls that are useful for acceptors.

+

Structs§

  • An error returned from the TLS implementation.
  • A wrapper around a native_tls::TlsAcceptor, providing an async accept +method.
\ No newline at end of file diff --git a/actix_tls/accept/native_tls/reexports/sidebar-items.js b/actix_tls/accept/native_tls/reexports/sidebar-items.js new file mode 100644 index 00000000..f27cc92a --- /dev/null +++ b/actix_tls/accept/native_tls/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["Error","TlsAcceptor"]}; \ No newline at end of file diff --git a/actix_tls/accept/native_tls/reexports/struct.Error.html b/actix_tls/accept/native_tls/reexports/struct.Error.html new file mode 100644 index 00000000..c30763b9 --- /dev/null +++ b/actix_tls/accept/native_tls/reexports/struct.Error.html @@ -0,0 +1,18 @@ +Error in actix_tls::accept::native_tls::reexports - Rust
actix_tls::accept::native_tls::reexports

Struct Error

pub struct Error(/* private fields */);
Expand description

An error returned from the TLS implementation.

+

Trait Implementations§

§

impl Debug for Error

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Display for Error

§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Error for Error

§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
§

impl From<Error> for Error

§

fn from(err: Error) -> Error

Converts to this type from the input type.

Auto Trait Implementations§

§

impl Freeze for Error

§

impl !RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl !UnwindSafe for Error

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/native_tls/reexports/struct.TlsAcceptor.html b/actix_tls/accept/native_tls/reexports/struct.TlsAcceptor.html new file mode 100644 index 00000000..14ddc3aa --- /dev/null +++ b/actix_tls/accept/native_tls/reexports/struct.TlsAcceptor.html @@ -0,0 +1,29 @@ +TlsAcceptor in actix_tls::accept::native_tls::reexports - Rust
actix_tls::accept::native_tls::reexports

Struct TlsAcceptor

source
pub struct TlsAcceptor(/* private fields */);
Expand description

A wrapper around a native_tls::TlsAcceptor, providing an async accept +method.

+

Implementations§

source§

impl TlsAcceptor

source

pub async fn accept<S>(&self, stream: S) -> Result<TlsStream<S>, Error>
where + S: AsyncRead + AsyncWrite + Unpin,

Accepts a new client connection with the provided stream.

+

This function will internally call TlsAcceptor::accept to connect +the stream and returns a future representing the resolution of the +connection operation. The returned future will resolve to either +TlsStream<S> or Error depending if it’s successful or not.

+

This is typically used after a new socket has been accepted from a +TcpListener. That socket is then passed to this function to perform +the server half of accepting a client connection.

+

Trait Implementations§

source§

impl Clone for TlsAcceptor

source§

fn clone(&self) -> TlsAcceptor

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for TlsAcceptor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl From<TlsAcceptor> for TlsAcceptor

source§

fn from(inner: TlsAcceptor) -> TlsAcceptor

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/native_tls/sidebar-items.js b/actix_tls/accept/native_tls/sidebar-items.js new file mode 100644 index 00000000..609abc9a --- /dev/null +++ b/actix_tls/accept/native_tls/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["Acceptor","AcceptorService","TlsStream"]}; \ No newline at end of file diff --git a/actix_tls/accept/native_tls/struct.Acceptor.html b/actix_tls/accept/native_tls/struct.Acceptor.html new file mode 100644 index 00000000..6b6aec10 --- /dev/null +++ b/actix_tls/accept/native_tls/struct.Acceptor.html @@ -0,0 +1,38 @@ +Acceptor in actix_tls::accept::native_tls - Rust
actix_tls::accept::native_tls

Struct Acceptor

source
pub struct Acceptor { /* private fields */ }
Expand description

Accept TLS connections via the native-tls crate.

+

Implementations§

source§

impl Acceptor

source

pub fn new(acceptor: TlsAcceptor) -> Self

Constructs native-tls based acceptor service factory.

+
source

pub fn set_handshake_timeout( + &mut self, + handshake_timeout: Duration, +) -> &mut Self

Limit the amount of time that the acceptor will wait for a TLS handshake to complete.

+

Default timeout is 3 seconds.

+

Trait Implementations§

source§

impl Clone for Acceptor

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<IO: ActixStream + 'static> ServiceFactory<IO> for Acceptor

source§

type Response = TlsStream<IO>

Responses given by the created services.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = AcceptorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Acceptor as ServiceFactory<IO>>::Service, <Acceptor as ServiceFactory<IO>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/native_tls/struct.AcceptorService.html b/actix_tls/accept/native_tls/struct.AcceptorService.html new file mode 100644 index 00000000..55182088 --- /dev/null +++ b/actix_tls/accept/native_tls/struct.AcceptorService.html @@ -0,0 +1,27 @@ +AcceptorService in actix_tls::accept::native_tls - Rust
actix_tls::accept::native_tls

Struct AcceptorService

source
pub struct AcceptorService { /* private fields */ }
Expand description

Native-TLS based acceptor service.

+

Trait Implementations§

source§

impl<IO: ActixStream + 'static> Service<IO> for AcceptorService

source§

type Response = TlsStream<IO>

Responses given by the service.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the service when polling readiness or executing call.
source§

type Future = Pin<Box<dyn Future<Output = Result<<AcceptorService as Service<IO>>::Response, <AcceptorService as Service<IO>>::Error>>>>

The future response value.
source§

fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, io: IO) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/native_tls/struct.TlsStream.html b/actix_tls/accept/native_tls/struct.TlsStream.html new file mode 100644 index 00000000..b5ee666f --- /dev/null +++ b/actix_tls/accept/native_tls/struct.TlsStream.html @@ -0,0 +1,39 @@ +TlsStream in actix_tls::accept::native_tls - Rust
actix_tls::accept::native_tls

Struct TlsStream

source
pub struct TlsStream<IO>(/* private fields */);
Expand description

Wraps a native-tls based async TLS stream in order to implement [ActixStream].

+

Methods from Deref<Target = TlsStream<IO>>§

source

pub fn get_ref(&self) -> &TlsStream<AllowStd<S>>

Returns a shared reference to the inner stream.

+
source

pub fn get_mut(&mut self) -> &mut TlsStream<AllowStd<S>>

Returns a mutable reference to the inner stream.

+

Trait Implementations§

source§

impl<IO: ActixStream> AsyncRead for TlsStream<IO>

source§

fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<()>>

Attempts to read from the AsyncRead into buf. Read more
source§

impl<IO: ActixStream> AsyncWrite for TlsStream<IO>

source§

fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
source§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
source§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
source§

impl<IO> Deref for TlsStream<IO>

source§

type Target = TlsStream<IO>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<IO> DerefMut for TlsStream<IO>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<IO> From<TlsStream<IO>> for TlsStream<IO>

source§

fn from(from: TlsStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>

§

impl<IO> RefUnwindSafe for TlsStream<IO>
where + IO: RefUnwindSafe,

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> UnwindSafe for TlsStream<IO>
where + IO: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/index.html b/actix_tls/accept/openssl/index.html new file mode 100644 index 00000000..f8b3a22e --- /dev/null +++ b/actix_tls/accept/openssl/index.html @@ -0,0 +1,3 @@ +actix_tls::accept::openssl - Rust
actix_tls::accept

Module openssl

source
Expand description

openssl based TLS acceptor service.

+

See Acceptor for main service factory docs.

+

Modules§

  • Re-exports from openssl that are useful for acceptors.

Structs§

  • Accept TLS connections via the openssl crate.
  • OpenSSL based acceptor service.
  • Wraps an openssl based async TLS stream in order to implement [ActixStream].
\ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/enum.HandshakeError.html b/actix_tls/accept/openssl/reexports/enum.HandshakeError.html new file mode 100644 index 00000000..f655b2df --- /dev/null +++ b/actix_tls/accept/openssl/reexports/enum.HandshakeError.html @@ -0,0 +1,32 @@ +HandshakeError in actix_tls::accept::openssl::reexports - Rust
actix_tls::accept::openssl::reexports

Enum HandshakeError

source
pub enum HandshakeError<S> {
+    SetupFailure(ErrorStack),
+    Failure(MidHandshakeSslStream<S>),
+    WouldBlock(MidHandshakeSslStream<S>),
+}
Expand description

An error or intermediate state after a TLS handshake attempt.

+

Variants§

§

SetupFailure(ErrorStack)

Setup failed.

+
§

Failure(MidHandshakeSslStream<S>)

The handshake failed.

+
§

WouldBlock(MidHandshakeSslStream<S>)

The handshake encountered a WouldBlock error midway through.

+

This error will never be returned for blocking streams.

+

Trait Implementations§

source§

impl<S> Debug for HandshakeError<S>
where + S: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl<S> Display for HandshakeError<S>
where + S: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl<S> Error for HandshakeError<S>
where + S: Debug,

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
source§

impl<S> From<ErrorStack> for HandshakeError<S>

source§

fn from(e: ErrorStack) -> HandshakeError<S>

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<S> Freeze for HandshakeError<S>

§

impl<S> !RefUnwindSafe for HandshakeError<S>

§

impl<S> Send for HandshakeError<S>
where + S: Send,

§

impl<S> Sync for HandshakeError<S>
where + S: Sync,

§

impl<S> Unpin for HandshakeError<S>
where + S: Unpin,

§

impl<S> !UnwindSafe for HandshakeError<S>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/index.html b/actix_tls/accept/openssl/reexports/index.html new file mode 100644 index 00000000..d4e28d0c --- /dev/null +++ b/actix_tls/accept/openssl/reexports/index.html @@ -0,0 +1,2 @@ +actix_tls::accept::openssl::reexports - Rust
actix_tls::accept::openssl

Module reexports

source
Expand description

Re-exports from openssl that are useful for acceptors.

+

Structs§

Enums§

  • An error or intermediate state after a TLS handshake attempt.
\ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/sidebar-items.js b/actix_tls/accept/openssl/reexports/sidebar-items.js new file mode 100644 index 00000000..319753a1 --- /dev/null +++ b/actix_tls/accept/openssl/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["HandshakeError"],"struct":["AlpnError","Error","Ssl","SslAcceptor","SslAcceptorBuilder"]}; \ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/struct.AlpnError.html b/actix_tls/accept/openssl/reexports/struct.AlpnError.html new file mode 100644 index 00000000..defe142f --- /dev/null +++ b/actix_tls/accept/openssl/reexports/struct.AlpnError.html @@ -0,0 +1,24 @@ +AlpnError in actix_tls::accept::openssl::reexports - Rust
actix_tls::accept::openssl::reexports

Struct AlpnError

source
pub struct AlpnError(/* private fields */);
Expand description

An error returned from an ALPN selection callback.

+

Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.

+

Implementations§

source§

impl AlpnError

source

pub const ALERT_FATAL: AlpnError = _

Terminate the handshake with a fatal alert.

+

Requires OpenSSL 1.1.0 or newer.

+
source

pub const NOACK: AlpnError = _

Do not select a protocol, but continue the handshake.

+

Trait Implementations§

source§

impl Clone for AlpnError

source§

fn clone(&self) -> AlpnError

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for AlpnError

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl PartialEq for AlpnError

source§

fn eq(&self, other: &AlpnError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.6.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl Copy for AlpnError

source§

impl Eq for AlpnError

source§

impl StructuralPartialEq for AlpnError

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/struct.Error.html b/actix_tls/accept/openssl/reexports/struct.Error.html new file mode 100644 index 00000000..a90f029d --- /dev/null +++ b/actix_tls/accept/openssl/reexports/struct.Error.html @@ -0,0 +1,18 @@ +Error in actix_tls::accept::openssl::reexports - Rust
actix_tls::accept::openssl::reexports

Struct Error

source
pub struct Error { /* private fields */ }
Expand description

An SSL error.

+

Implementations§

source§

impl Error

source

pub fn code(&self) -> ErrorCode

source

pub fn io_error(&self) -> Option<&Error>

source

pub fn into_io_error(self) -> Result<Error, Error>

source

pub fn ssl_error(&self) -> Option<&ErrorStack>

Trait Implementations§

source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Error for Error

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
source§

impl From<ErrorStack> for Error

source§

fn from(e: ErrorStack) -> Error

Converts to this type from the input type.

Auto Trait Implementations§

§

impl Freeze for Error

§

impl !RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl !UnwindSafe for Error

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/struct.Ssl.html b/actix_tls/accept/openssl/reexports/struct.Ssl.html new file mode 100644 index 00000000..1f26d809 --- /dev/null +++ b/actix_tls/accept/openssl/reexports/struct.Ssl.html @@ -0,0 +1,330 @@ +Ssl in actix_tls::accept::openssl::reexports - Rust
actix_tls::accept::openssl::reexports

Struct Ssl

source
pub struct Ssl(/* private fields */);
Expand description

The state of an SSL/TLS session.

+

Ssl objects are created from an SslContext, which provides configuration defaults. +These defaults can be overridden on a per-Ssl basis, however.

+

Implementations§

source§

impl Ssl

source

pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
where + T: 'static + Sync + Send,

Returns a new extra data index.

+

Each invocation of this function is guaranteed to return a distinct index. These can be used +to store data in the context that can be retrieved later by callbacks, for example.

+

This corresponds to SSL_get_ex_new_index.

+
source

pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack>

Creates a new Ssl.

+

This corresponds to SSL_new.

+

This corresponds to SSL_new.

+
source

pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where + S: Read + Write,

Initiates a client-side TLS handshake.

+

This corresponds to SSL_connect.

+
§Warning
+

OpenSSL’s default configuration is insecure. It is highly recommended to use +SslConnector rather than Ssl directly, as it manages that configuration.

+

This corresponds to SSL_connect.

+
source

pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where + S: Read + Write,

Initiates a server-side TLS handshake.

+

This corresponds to SSL_accept.

+
§Warning
+

OpenSSL’s default configuration is insecure. It is highly recommended to use +SslAcceptor rather than Ssl directly, as it manages that configuration.

+

This corresponds to SSL_accept.

+

Methods from Deref<Target = SslRef>§

source

pub fn set_connect_state(&mut self)

Configure as an outgoing stream from a client.

+

This corresponds to SSL_set_connect_state.

+
source

pub fn set_accept_state(&mut self)

Configure as an incoming stream to a server.

+

This corresponds to SSL_set_accept_state.

+
source

pub fn set_verify(&mut self, mode: SslVerifyMode)

Like SslContextBuilder::set_verify.

+

This corresponds to SSL_set_verify.

+
source

pub fn verify_mode(&self) -> SslVerifyMode

Returns the verify mode that was set using set_verify.

+

This corresponds to SSL_set_verify_mode.

+
source

pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
where + F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,

source

pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack>

Like SslContextBuilder::set_tmp_dh.

+

This corresponds to SSL_set_tmp_dh.

+
source

pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,

source

pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack>

source

pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack>

Like SslContextBuilder::set_alpn_protos.

+

Requires BoringSSL or OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_set_alpn_protos.

+
source

pub fn current_cipher(&self) -> Option<&SslCipherRef>

Returns the current cipher if the session is active.

+

This corresponds to SSL_get_current_cipher.

+
source

pub fn state_string(&self) -> &'static str

Returns a short string describing the state of the session.

+

This corresponds to SSL_state_string.

+
source

pub fn state_string_long(&self) -> &'static str

Returns a longer string describing the state of the session.

+

This corresponds to SSL_state_string_long.

+
source

pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack>

Sets the host name to be sent to the server for Server Name Indication (SNI).

+

It has no effect for a server-side connection.

+

This corresponds to SSL_set_tlsext_host_name.

+
source

pub fn peer_certificate(&self) -> Option<X509>

Returns the peer’s certificate, if present.

+

This corresponds to SSL_get_peer_certificate.

+
source

pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>>

Returns the certificate chain of the peer, if present.

+

On the client side, the chain includes the leaf certificate, but on the server side it does +not. Fun!

+

This corresponds to SSL_get_peer_cert_chain.

+
source

pub fn verified_chain(&self) -> Option<&StackRef<X509>>

Returns the verified certificate chain of the peer, including the leaf certificate.

+

If verification was not successful (i.e. verify_result does not return +X509VerifyResult::OK), this chain may be incomplete or invalid.

+

Requires OpenSSL 1.1.0 or newer.

+

This corresponds to SSL_get0_verified_chain.

+
source

pub fn certificate(&self) -> Option<&X509Ref>

Like [SslContext::certificate].

+

This corresponds to SSL_get_certificate.

+
source

pub fn private_key(&self) -> Option<&PKeyRef<Private>>

Like SslContext::private_key.

+

This corresponds to SSL_get_privatekey.

+
source

pub fn version(&self) -> &str

👎Deprecated since 0.10.5: renamed to version_str
source

pub fn version2(&self) -> Option<SslVersion>

Returns the protocol version of the session.

+

This corresponds to SSL_version.

+
source

pub fn version_str(&self) -> &'static str

Returns a string describing the protocol version of the session.

+

This corresponds to SSL_get_version.

+
source

pub fn selected_alpn_protocol(&self) -> Option<&[u8]>

Returns the protocol selected via Application Layer Protocol Negotiation (ALPN).

+

The protocol’s name is returned is an opaque sequence of bytes. It is up to the client +to interpret it.

+

Requires BoringSSL or OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_get0_alpn_selected.

+
source

pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack>

Enables the DTLS extension “use_srtp” as defined in RFC5764.

+

This corresponds to SSL_set_tlsext_use_srtp.

+

This corresponds to SSL_set_tlsext_use_srtp.

+
source

pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>>

Gets all SRTP profiles that are enabled for handshake via set_tlsext_use_srtp

+

DTLS extension “use_srtp” as defined in RFC5764 has to be enabled.

+

This corresponds to SSL_get_srtp_profiles.

+

This corresponds to SSL_get_srtp_profiles.

+
source

pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef>

Gets the SRTP profile selected by handshake.

+

DTLS extension “use_srtp” as defined in RFC5764 has to be enabled.

+

This corresponds to SSL_get_selected_srtp_profile.

+
source

pub fn pending(&self) -> usize

Returns the number of bytes remaining in the currently processed TLS record.

+

If this is greater than 0, the next call to read will not call down to the underlying +stream.

+

This corresponds to SSL_pending.

+
source

pub fn servername(&self, type_: NameType) -> Option<&str>

Returns the servername sent by the client via Server Name Indication (SNI).

+

It is only useful on the server side.

+
§Note
+

While the SNI specification requires that servernames be valid domain names (and therefore +ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client +is not valid UTF-8, this function will return None. The servername_raw method returns +the raw bytes and does not have this restriction.

+

This corresponds to SSL_get_servername.

+
source

pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]>

Returns the servername sent by the client via Server Name Indication (SNI).

+

It is only useful on the server side.

+
§Note
+

Unlike servername, this method does not require the name be valid UTF-8.

+

This corresponds to SSL_get_servername.

+
source

pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack>

Changes the context corresponding to the current connection.

+

It is most commonly used in the Server Name Indication (SNI) callback.

+

This corresponds to SSL_set_SSL_CTX.

+
source

pub fn ssl_context(&self) -> &SslContextRef

Returns the context corresponding to the current connection.

+

This corresponds to SSL_get_SSL_CTX.

+
source

pub fn param_mut(&mut self) -> &mut X509VerifyParamRef

Returns a mutable reference to the X509 verification configuration.

+

Requires BoringSSL or OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_get0_param.

+
source

pub fn verify_result(&self) -> X509VerifyResult

Returns the certificate verification result.

+

This corresponds to SSL_get_verify_result.

+
source

pub fn session(&self) -> Option<&SslSessionRef>

Returns a shared reference to the SSL session.

+

This corresponds to SSL_get_session.

+
source

pub fn client_random(&self, buf: &mut [u8]) -> usize

Copies the client_random value sent by the client in the TLS handshake into a buffer.

+

Returns the number of bytes copied, or if the buffer is empty, the size of the client_random +value.

+

Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.

+

This corresponds to SSL_get_client_random.

+
source

pub fn server_random(&self, buf: &mut [u8]) -> usize

Copies the server_random value sent by the server in the TLS handshake into a buffer.

+

Returns the number of bytes copied, or if the buffer is empty, the size of the server_random +value.

+

Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.

+

This corresponds to SSL_get_server_random.

+
source

pub fn export_keying_material( + &self, + out: &mut [u8], + label: &str, + context: Option<&[u8]>, +) -> Result<(), ErrorStack>

Derives keying material for application use in accordance to RFC 5705.

+

This corresponds to SSL_export_keying_material.

+
source

pub fn export_keying_material_early( + &self, + out: &mut [u8], + label: &str, + context: &[u8], +) -> Result<(), ErrorStack>

Derives keying material for application use in accordance to RFC 5705.

+

This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no +context. Therefore, unlike export_keying_material, context must always be supplied.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_export_keying_material_early.

+
source

pub unsafe fn set_session( + &mut self, + session: &SslSessionRef, +) -> Result<(), ErrorStack>

Sets the session to be used.

+

This should be called before the handshake to attempt to reuse a previously established +session. If the server is not willing to reuse the session, a new one will be transparently +negotiated.

+
§Safety
+

The caller of this method is responsible for ensuring that the session is associated +with the same SslContext as this Ssl.

+

This corresponds to SSL_set_session.

+
source

pub fn session_reused(&self) -> bool

Determines if the session provided to set_session was successfully reused.

+

This corresponds to SSL_session_reused.

+
source

pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack>

Sets the status response a client wishes the server to reply with.

+

This corresponds to SSL_set_tlsext_status_type.

+
source

pub fn extms_support(&self) -> Option<bool>

Determines if current session used Extended Master Secret

+

Returns None if the handshake is still in-progress.

+

This corresponds to SSL_get_extms_support.

+
source

pub fn ocsp_status(&self) -> Option<&[u8]>

Returns the server’s OCSP response, if present.

+

This corresponds to SSL_get_tlsext_status_ocsp_resp.

+
source

pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack>

Sets the OCSP response to be returned to the client.

+

This corresponds to SSL_set_tlsext_status_oscp_resp.

+
source

pub fn is_server(&self) -> bool

Determines if this Ssl is configured for server-side or client-side use.

+

This corresponds to SSL_is_server.

+
source

pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T)

Sets the extra data at the specified index.

+

This can be used to provide data to callbacks registered with the context. Use the +Ssl::new_ex_index method to create an Index.

+

This corresponds to SSL_set_ex_data.

+
source

pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T>

Returns a reference to the extra data at the specified index.

+

This corresponds to SSL_get_ex_data.

+
source

pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T>

Returns a mutable reference to the extra data at the specified index.

+

This corresponds to SSL_get_ex_data.

+
source

pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack>

Sets the maximum amount of early data that will be accepted on this connection.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+

This corresponds to SSL_set_max_early_data.

+
source

pub fn max_early_data(&self) -> u32

Gets the maximum amount of early data that can be sent on this connection.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+

This corresponds to SSL_get_max_early_data.

+
source

pub fn finished(&self, buf: &mut [u8]) -> usize

Copies the contents of the last Finished message sent to the peer into the provided buffer.

+

The total size of the message is returned, so this can be used to determine the size of the +buffer required.

+

This corresponds to SSL_get_finished.

+
source

pub fn peer_finished(&self, buf: &mut [u8]) -> usize

Copies the contents of the last Finished message received from the peer into the provided +buffer.

+

The total size of the message is returned, so this can be used to determine the size of the +buffer required.

+

This corresponds to SSL_get_peer_finished.

+
source

pub fn is_init_finished(&self) -> bool

Determines if the initial handshake has been completed.

+

This corresponds to SSL_is_init_finished.

+
source

pub fn client_hello_isv2(&self) -> bool

Determines if the client’s hello message is in the SSLv2 format.

+

This can only be used inside of the client hello callback. Otherwise, false is returned.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_client_hello_isv2.

+
source

pub fn client_hello_legacy_version(&self) -> Option<SslVersion>

Returns the legacy version field of the client’s hello message.

+

This can only be used inside of the client hello callback. Otherwise, None is returned.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_client_hello_get0_legacy_version.

+
source

pub fn client_hello_random(&self) -> Option<&[u8]>

Returns the random field of the client’s hello message.

+

This can only be used inside of the client hello callback. Otherwise, None is returned.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_client_hello_get0_random.

+
source

pub fn client_hello_session_id(&self) -> Option<&[u8]>

Returns the session ID field of the client’s hello message.

+

This can only be used inside of the client hello callback. Otherwise, None is returned.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_client_hello_get0_session_id.

+
source

pub fn client_hello_ciphers(&self) -> Option<&[u8]>

Returns the ciphers field of the client’s hello message.

+

This can only be used inside of the client hello callback. Otherwise, None is returned.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_client_hello_get0_ciphers.

+
source

pub fn bytes_to_cipher_list( + &self, + bytes: &[u8], + isv2format: bool, +) -> Result<CipherLists, ErrorStack>

Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites +are ignored.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_bytes_to_cipher_list.

+
source

pub fn client_hello_compression_methods(&self) -> Option<&[u8]>

Returns the compression methods field of the client’s hello message.

+

This can only be used inside of the client hello callback. Otherwise, None is returned.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_client_hello_get0_compression_methods.

+
source

pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack>

Sets the MTU used for DTLS connections.

+

This corresponds to SSL_set_mtu.

+
source

pub fn psk_identity_hint(&self) -> Option<&[u8]>

Returns the PSK identity hint used during connection setup.

+

May return None if no PSK identity hint was used during the connection setup.

+

This corresponds to SSL_get_psk_identity_hint.

+
source

pub fn psk_identity(&self) -> Option<&[u8]>

Returns the PSK identity used during connection setup.

+

This corresponds to SSL_get_psk_identity.

+
source

pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack>

This corresponds to SSL_add0_chain_cert.

+
source

pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack>

Sets a new default TLS/SSL method for SSL objects

+
source

pub fn set_private_key_file<P>( + &mut self, + path: P, + ssl_file_type: SslFiletype, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads the private key from a file.

+

This corresponds to SSL_use_Private_Key_file.

+
source

pub fn set_private_key( + &mut self, + pkey: &PKeyRef<Private>, +) -> Result<(), ErrorStack>

Sets the private key.

+

This corresponds to SSL_use_PrivateKey.

+
source

pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack>

Sets the certificate

+

This corresponds to SSL_use_certificate.

+
source

pub fn set_certificate_chain_file<P>( + &mut self, + path: P, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads a certificate chain from a file.

+

The file should contain a sequence of PEM-formatted certificates, the first being the leaf +certificate, and the remainder forming the chain of certificates up to and including the +trusted root certificate.

+

This corresponds to SSL_use_certificate_chain_file.

+
source

pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack>

Sets ca certificate that client trusted

+

This corresponds to SSL_add_client_CA.

+
source

pub fn set_client_ca_list(&mut self, list: Stack<X509Name>)

This corresponds to SSL_set_client_CA_list.

+
source

pub fn set_min_proto_version( + &mut self, + version: Option<SslVersion>, +) -> Result<(), ErrorStack>

Sets the minimum supported protocol version.

+

A value of None will enable protocol versions down to the lowest version supported by +OpenSSL.

+

Requires BoringSSL or OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_set_min_proto_version.

+
source

pub fn set_max_proto_version( + &mut self, + version: Option<SslVersion>, +) -> Result<(), ErrorStack>

Sets the maximum supported protocol version.

+

A value of None will enable protocol versions up to the highest version supported by +OpenSSL.

+

Requires BoringSSL or OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_set_max_proto_version.

+
source

pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack>

Sets the list of supported ciphers for the TLSv1.3 protocol.

+

The set_cipher_list method controls the cipher suites for protocols before TLSv1.3.

+

The format consists of TLSv1.3 cipher suite names separated by : characters in order of +preference.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+

This corresponds to SSL_set_ciphersuites.

+
source

pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack>

Sets the list of supported ciphers for protocols before TLSv1.3.

+

The set_ciphersuites method controls the cipher suites for TLSv1.3.

+

See ciphers for details on the format.

+

This corresponds to SSL_set_cipher_list.

+
source

pub fn set_verify_cert_store( + &mut self, + cert_store: X509Store, +) -> Result<(), ErrorStack>

Set the certificate store used for certificate verification

+

This corresponds to SSL_set_cert_store.

+
source

pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack>

Sets the number of TLS 1.3 session tickets that will be sent to a client after a full +handshake.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_set_num_tickets.

+
source

pub fn num_tickets(&self) -> usize

Gets the number of TLS 1.3 session tickets that will be sent to a client after a full +handshake.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_get_num_tickets.

+
source

pub fn set_security_level(&mut self, level: u32)

Set the context’s security level to a value between 0 and 5, inclusive. +A security value of 0 allows allows all parameters and algorithms.

+

Requires OpenSSL 1.1.0 or newer.

+

This corresponds to SSL_set_security_level.

+
source

pub fn security_level(&self) -> u32

Get the connection’s security level, which controls the allowed parameters +and algorithms.

+

Requires OpenSSL 1.1.0 or newer.

+

This corresponds to SSL_get_security_level.

+
source

pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack>

Get the temporary key provided by the peer that is used during key +exchange.

+

This corresponds to SSL_get_peer_tmp_key.

+
source

pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack>

Returns the temporary key from the local end of the connection that is +used during key exchange.

+

This corresponds to SSL_get_tmp_key.

+

Trait Implementations§

source§

impl AsRef<SslRef> for Ssl

source§

fn as_ref(&self) -> &SslRef

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl Borrow<SslRef> for Ssl

source§

fn borrow(&self) -> &SslRef

Immutably borrows from an owned value. Read more
source§

impl Debug for Ssl

source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Deref for Ssl

source§

type Target = SslRef

The resulting type after dereferencing.
source§

fn deref(&self) -> &SslRef

Dereferences the value.
source§

impl DerefMut for Ssl

source§

fn deref_mut(&mut self) -> &mut SslRef

Mutably dereferences the value.
source§

impl Drop for Ssl

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl ForeignType for Ssl

source§

type CType = SSL

The raw C type.
source§

type Ref = SslRef

The type representing a reference to this type.
source§

unsafe fn from_ptr(ptr: *mut SSL) -> Ssl

Constructs an instance of this type from its raw type.
source§

fn as_ptr(&self) -> *mut SSL

Returns a raw pointer to the wrapped value.
source§

impl Send for Ssl

source§

impl Sync for Ssl

Auto Trait Implementations§

§

impl Freeze for Ssl

§

impl RefUnwindSafe for Ssl

§

impl Unpin for Ssl

§

impl UnwindSafe for Ssl

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/struct.SslAcceptor.html b/actix_tls/accept/openssl/reexports/struct.SslAcceptor.html new file mode 100644 index 00000000..09c1f45e --- /dev/null +++ b/actix_tls/accept/openssl/reexports/struct.SslAcceptor.html @@ -0,0 +1,48 @@ +SslAcceptor in actix_tls::accept::openssl::reexports - Rust
actix_tls::accept::openssl::reexports

Struct SslAcceptor

source
pub struct SslAcceptor(/* private fields */);
Expand description

A type which wraps server-side streams in a TLS session.

+

OpenSSL’s default configuration is highly insecure. This connector manages the OpenSSL +structures, configuring cipher suites, session options, and more.

+

Implementations§

source§

impl SslAcceptor

source

pub fn mozilla_intermediate_v5( + method: SslMethod, +) -> Result<SslAcceptorBuilder, ErrorStack>

Creates a new builder configured to connect to non-legacy clients. This should generally be +considered a reasonable default choice.

+

This corresponds to the intermediate configuration of version 5 of Mozilla’s server side TLS +recommendations. See its documentation for more details on specifics.

+
source

pub fn mozilla_modern_v5( + method: SslMethod, +) -> Result<SslAcceptorBuilder, ErrorStack>

Creates a new builder configured to connect to modern clients.

+

This corresponds to the modern configuration of version 5 of Mozilla’s server side TLS recommendations. +See its documentation for more details on specifics.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+
source

pub fn mozilla_intermediate( + method: SslMethod, +) -> Result<SslAcceptorBuilder, ErrorStack>

Creates a new builder configured to connect to non-legacy clients. This should generally be +considered a reasonable default choice.

+

This corresponds to the intermediate configuration of version 4 of Mozilla’s server side TLS +recommendations. See its documentation for more details on specifics.

+
source

pub fn mozilla_modern( + method: SslMethod, +) -> Result<SslAcceptorBuilder, ErrorStack>

Creates a new builder configured to connect to modern clients.

+

This corresponds to the modern configuration of version 4 of Mozilla’s server side TLS recommendations. +See its documentation for more details on specifics.

+
source

pub fn accept<S>(&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where + S: Read + Write,

Initiates a server-side TLS session on a stream.

+
source

pub fn into_context(self) -> SslContext

Consumes the SslAcceptor, returning the inner raw SslContext.

+
source

pub fn context(&self) -> &SslContextRef

Returns a shared reference to the inner raw SslContext.

+

Trait Implementations§

source§

impl Clone for SslAcceptor

source§

fn clone(&self) -> SslAcceptor

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/reexports/struct.SslAcceptorBuilder.html b/actix_tls/accept/openssl/reexports/struct.SslAcceptorBuilder.html new file mode 100644 index 00000000..ab72d0af --- /dev/null +++ b/actix_tls/accept/openssl/reexports/struct.SslAcceptorBuilder.html @@ -0,0 +1,326 @@ +SslAcceptorBuilder in actix_tls::accept::openssl::reexports - Rust
actix_tls::accept::openssl::reexports

Struct SslAcceptorBuilder

source
pub struct SslAcceptorBuilder(/* private fields */);
Expand description

A builder for SslAcceptors.

+

Implementations§

source§

impl SslAcceptorBuilder

source

pub fn build(self) -> SslAcceptor

Consumes the builder, returning a SslAcceptor.

+

Methods from Deref<Target = SslContextBuilder>§

source

pub fn as_ptr(&self) -> *mut SSL_CTX

Returns a pointer to the raw OpenSSL value.

+
source

pub fn set_verify(&mut self, mode: SslVerifyMode)

Configures the certificate verification method for new connections.

+

This corresponds to SSL_CTX_set_verify.

+
source

pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
where + F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,

Configures the certificate verification method for new connections and +registers a verification callback.

+

The callback is passed a boolean indicating if OpenSSL’s internal verification succeeded as +well as a reference to the X509StoreContext which can be used to examine the certificate +chain. It should return a boolean indicating if verification succeeded.

+

This corresponds to SSL_CTX_set_verify.

+
source

pub fn set_servername_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,

Configures the server name indication (SNI) callback for new connections.

+

SNI is used to allow a single server to handle requests for multiple domains, each of which +has its own certificate chain and configuration.

+

Obtain the server name with the servername method and then set the corresponding context +with set_ssl_context

+

This corresponds to SSL_CTX_set_tlsext_servername_callback.

+
source

pub fn set_verify_depth(&mut self, depth: u32)

Sets the certificate verification depth.

+

If the peer’s certificate chain is longer than this value, verification will fail.

+

This corresponds to SSL_CTX_set_verify_depth.

+
source

pub fn set_verify_cert_store( + &mut self, + cert_store: X509Store, +) -> Result<(), ErrorStack>

Sets a custom certificate store for verifying peer certificates.

+

Requires OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_set0_verify_cert_store.

+
source

pub fn set_cert_store(&mut self, cert_store: X509Store)

Replaces the context’s certificate store.

+

This corresponds to SSL_CTX_set_cert_store.

+
source

pub fn set_read_ahead(&mut self, read_ahead: bool)

Controls read ahead behavior.

+

If enabled, OpenSSL will read as much data as is available from the underlying stream, +instead of a single record at a time.

+

It has no effect when used with DTLS.

+

This corresponds to SSL_CTX_set_read_ahead.

+
source

pub fn set_mode(&mut self, mode: SslMode) -> SslMode

Sets the mode used by the context, returning the previous mode.

+

This corresponds to SSL_CTX_set_mode.

+
source

pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack>

Sets the parameters to be used during ephemeral Diffie-Hellman key exchange.

+

This corresponds to SSL_CTX_set_tmp_dh.

+
source

pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,

Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman +key exchange.

+

The callback is provided with a reference to the Ssl for the session, as well as a boolean +indicating if the selected cipher is export-grade, and the key length. The export and key +length options are archaic and should be ignored in almost all cases.

+

This corresponds to SSL_CTX_set_tmp_dh_callback.

+
source

pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack>

Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange.

+

This corresponds to SSL_CTX_set_tmp_ecdh.

+
source

pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack>

Use the default locations of trusted certificates for verification.

+

These locations are read from the SSL_CERT_FILE and SSL_CERT_DIR environment variables +if present, or defaults specified at OpenSSL build time otherwise.

+

This corresponds to SSL_CTX_set_default_verify_paths.

+
source

pub fn set_ca_file<P>(&mut self, file: P) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads trusted root certificates from a file.

+

The file should contain a sequence of PEM-formatted CA certificates.

+

This corresponds to SSL_CTX_load_verify_locations.

+
source

pub fn set_client_ca_list(&mut self, list: Stack<X509Name>)

Sets the list of CA names sent to the client.

+

The CA certificates must still be added to the trust root - they are not automatically set +as trusted by this method.

+

This corresponds to SSL_CTX_set_client_CA_list.

+
source

pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack>

Add the provided CA certificate to the list sent by the server to the client when +requesting client-side TLS authentication.

+

This corresponds to SSL_CTX_add_client_CA.

+
source

pub fn set_session_id_context( + &mut self, + sid_ctx: &[u8], +) -> Result<(), ErrorStack>

Set the context identifier for sessions.

+

This value identifies the server’s session cache to clients, telling them when they’re +able to reuse sessions. It should be set to a unique value per server, unless multiple +servers share a session cache.

+

This value should be set when using client certificates, or each request will fail its +handshake and need to be restarted.

+

This corresponds to SSL_CTX_set_session_id_context.

+
source

pub fn set_certificate_file<P>( + &mut self, + file: P, + file_type: SslFiletype, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads a leaf certificate from a file.

+

Only a single certificate will be loaded - use add_extra_chain_cert to add the remainder +of the certificate chain, or set_certificate_chain_file to load the entire chain from a +single file.

+

This corresponds to SSL_CTX_use_certificate_file.

+
source

pub fn set_certificate_chain_file<P>( + &mut self, + file: P, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads a certificate chain from a file.

+

The file should contain a sequence of PEM-formatted certificates, the first being the leaf +certificate, and the remainder forming the chain of certificates up to and including the +trusted root certificate.

+

This corresponds to SSL_CTX_use_certificate_chain_file.

+
source

pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack>

Sets the leaf certificate.

+

Use add_extra_chain_cert to add the remainder of the certificate chain.

+

This corresponds to SSL_CTX_use_certificate.

+
source

pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack>

Appends a certificate to the certificate chain.

+

This chain should contain all certificates necessary to go from the certificate specified by +set_certificate to a trusted root.

+

This corresponds to SSL_CTX_add_extra_chain_cert.

+
source

pub fn set_private_key_file<P>( + &mut self, + file: P, + file_type: SslFiletype, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads the private key from a file.

+

This corresponds to SSL_CTX_use_PrivateKey_file.

+
source

pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
where + T: HasPrivate,

Sets the private key.

+

This corresponds to SSL_CTX_use_PrivateKey.

+
source

pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack>

Sets the list of supported ciphers for protocols before TLSv1.3.

+

The set_ciphersuites method controls the cipher suites for TLSv1.3.

+

See ciphers for details on the format.

+

This corresponds to SSL_CTX_set_cipher_list.

+
source

pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack>

Sets the list of supported ciphers for the TLSv1.3 protocol.

+

The set_cipher_list method controls the cipher suites for protocols before TLSv1.3.

+

The format consists of TLSv1.3 cipher suite names separated by : characters in order of +preference.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+

This corresponds to SSL_CTX_set_ciphersuites.

+
source

pub fn set_options(&mut self, option: SslOptions) -> SslOptions

Sets the options used by the context, returning the old set.

+
§Note
+

This enables the specified options, but does not disable unspecified options. Use +clear_options for that.

+

This corresponds to SSL_CTX_set_options.

+
source

pub fn options(&self) -> SslOptions

Returns the options used by the context.

+

This corresponds to SSL_CTX_get_options.

+
source

pub fn clear_options(&mut self, option: SslOptions) -> SslOptions

Clears the options used by the context, returning the old set.

+

This corresponds to SSL_CTX_clear_options.

+
source

pub fn set_min_proto_version( + &mut self, + version: Option<SslVersion>, +) -> Result<(), ErrorStack>

Sets the minimum supported protocol version.

+

A value of None will enable protocol versions down to the lowest version supported by +OpenSSL.

+

Requires BoringSSL or OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_min_proto_version.

+
source

pub fn set_max_proto_version( + &mut self, + version: Option<SslVersion>, +) -> Result<(), ErrorStack>

Sets the maximum supported protocol version.

+

A value of None will enable protocol versions up to the highest version supported by +OpenSSL.

+

Requires BoringSSL or OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_max_proto_version.

+
source

pub fn min_proto_version(&mut self) -> Option<SslVersion>

Gets the minimum supported protocol version.

+

A value of None indicates that all versions down to the lowest version supported by +OpenSSL are enabled.

+

Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.

+

This corresponds to SSL_CTX_get_min_proto_version.

+
source

pub fn max_proto_version(&mut self) -> Option<SslVersion>

Gets the maximum supported protocol version.

+

A value of None indicates that all versions up to the highest version supported by +OpenSSL are enabled.

+

Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.

+

This corresponds to SSL_CTX_get_max_proto_version.

+
source

pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack>

Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN).

+

The input must be in ALPN “wire format”. It consists of a sequence of supported protocol +names prefixed by their byte length. For example, the protocol list consisting of spdy/1 +and http/1.1 is encoded as b"\x06spdy/1\x08http/1.1". The protocols are ordered by +preference.

+

Requires BoringSSL or OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_alpn_protos.

+
source

pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack>

Enables the DTLS extension “use_srtp” as defined in RFC5764.

+

This corresponds to SSL_CTX_set_tlsext_use_srtp.

+
source

pub fn set_alpn_select_callback<F>(&mut self, callback: F)
where + F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,

Sets the callback used by a server to select a protocol for Application Layer Protocol +Negotiation (ALPN).

+

The callback is provided with the client’s protocol list in ALPN wire format. See the +documentation for SslContextBuilder::set_alpn_protos for details. It should return one +of those protocols on success. The select_next_proto function implements the standard +protocol selection algorithm.

+

Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_alpn_select_cb.

+
source

pub fn check_private_key(&self) -> Result<(), ErrorStack>

Checks for consistency between the private key and certificate.

+

This corresponds to SSL_CTX_check_private_key.

+
source

pub fn cert_store(&self) -> &X509StoreBuilderRef

Returns a shared reference to the context’s certificate store.

+

This corresponds to SSL_CTX_get_cert_store.

+
source

pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef

Returns a mutable reference to the context’s certificate store.

+

This corresponds to SSL_CTX_get_cert_store.

+
source

pub fn verify_param(&self) -> &X509VerifyParamRef

Returns a reference to the X509 verification configuration.

+

Requires BoringSSL or OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_get0_param.

+
source

pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef

Returns a mutable reference to the X509 verification configuration.

+

Requires BoringSSL or OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_get0_param.

+
source

pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
where + F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,

Sets the callback dealing with OCSP stapling.

+

On the client side, this callback is responsible for validating the OCSP status response +returned by the server. The status may be retrieved with the SslRef::ocsp_status method. +A response of Ok(true) indicates that the OCSP status is valid, and a response of +Ok(false) indicates that the OCSP status is invalid and the handshake should be +terminated.

+

On the server side, this callback is responsible for setting the OCSP status response to be +returned to clients. The status may be set with the SslRef::set_ocsp_status method. A +response of Ok(true) indicates that the OCSP status should be returned to the client, and +Ok(false) indicates that the status should not be returned to the client.

+

This corresponds to SSL_CTX_set_tlsext_status_cb.

+
source

pub fn set_psk_client_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,

Sets the callback for providing an identity and pre-shared key for a TLS-PSK client.

+

The callback will be called with the SSL context, an identity hint if one was provided +by the server, a mutable slice for each of the identity and pre-shared key bytes. The +identity must be written as a null-terminated C string.

+

This corresponds to SSL_CTX_set_psk_client_callback.

+
source

pub fn set_psk_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,

👎Deprecated since 0.10.10: renamed to set_psk_client_callback
source

pub fn set_psk_server_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,

Sets the callback for providing an identity and pre-shared key for a TLS-PSK server.

+

The callback will be called with the SSL context, an identity provided by the client, +and, a mutable slice for the pre-shared key bytes. The callback returns the number of +bytes in the pre-shared key.

+

This corresponds to SSL_CTX_set_psk_server_callback.

+
source

pub fn set_new_session_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,

Sets the callback which is called when new sessions are negotiated.

+

This can be used by clients to implement session caching. While in TLSv1.2 the session is +available to access via SslRef::session immediately after the handshake completes, this +is not the case for TLSv1.3. There, a session is not generally available immediately, and +the server may provide multiple session tokens to the client over a single session. The new +session callback is a portable way to deal with both cases.

+

Note that session caching must be enabled for the callback to be invoked, and it defaults +off for clients. set_session_cache_mode controls that behavior.

+

This corresponds to SSL_CTX_sess_set_new_cb.

+
source

pub fn set_remove_session_callback<F>(&mut self, callback: F)
where + F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,

Sets the callback which is called when sessions are removed from the context.

+

Sessions can be removed because they have timed out or because they are considered faulty.

+

This corresponds to SSL_CTX_sess_set_remove_cb.

+
source

pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,

Sets the callback which is called when a client proposed to resume a session but it was not +found in the internal cache.

+

The callback is passed a reference to the session ID provided by the client. It should +return the session corresponding to that ID if available. This is only used for servers, not +clients.

+
§Safety
+

The returned SslSession must not be associated with a different SslContext.

+

This corresponds to SSL_CTX_sess_set_get_cb.

+
source

pub fn set_keylog_callback<F>(&mut self, callback: F)
where + F: Fn(&SslRef, &str) + 'static + Sync + Send,

Sets the TLS key logging callback.

+

The callback is invoked whenever TLS key material is generated, and is passed a line of NSS +SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message +traffic. The line does not contain a trailing newline.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_set_keylog_callback.

+
source

pub fn set_session_cache_mode( + &mut self, + mode: SslSessionCacheMode, +) -> SslSessionCacheMode

Sets the session caching mode use for connections made with the context.

+

Returns the previous session caching mode.

+

This corresponds to SSL_CTX_set_session_cache_mode.

+

Sets the callback for generating an application cookie for TLS1.3 +stateless handshakes.

+

The callback will be called with the SSL context and a slice into which the cookie +should be written. The callback should return the number of bytes written.

+

This corresponds to SSL_CTX_set_stateless_cookie_generate_cb.

+

Sets the callback for verifying an application cookie for TLS1.3 +stateless handshakes.

+

The callback will be called with the SSL context and the cookie supplied by the +client. It should return true if and only if the cookie is valid.

+

Note that the OpenSSL implementation independently verifies the integrity of +application cookies using an HMAC before invoking the supplied callback.

+

This corresponds to SSL_CTX_set_stateless_cookie_verify_cb.

+

Sets the callback for generating a DTLSv1 cookie

+

The callback will be called with the SSL context and a slice into which the cookie +should be written. The callback should return the number of bytes written.

+

This corresponds to SSL_CTX_set_cookie_generate_cb.

+

Sets the callback for verifying a DTLSv1 cookie

+

The callback will be called with the SSL context and the cookie supplied by the +client. It should return true if and only if the cookie is valid.

+

This corresponds to SSL_CTX_set_cookie_verify_cb.

+
source

pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T)

Sets the extra data at the specified index.

+

This can be used to provide data to callbacks registered with the context. Use the +SslContext::new_ex_index method to create an Index.

+

This corresponds to SSL_CTX_set_ex_data.

+
source

pub fn add_custom_ext<AddFn, ParseFn, T>( + &mut self, + ext_type: u16, + context: ExtensionContext, + add_cb: AddFn, + parse_cb: ParseFn, +) -> Result<(), ErrorStack>
where + AddFn: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert> + 'static + Sync + Send, + T: AsRef<[u8]> + 'static + Sync + Send, + ParseFn: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert> + 'static + Sync + Send,

Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_add_custom_ext.

+
source

pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack>

Sets the maximum amount of early data that will be accepted on incoming connections.

+

Defaults to 0.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+

This corresponds to SSL_CTX_set_max_early_data.

+
source

pub fn set_client_hello_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack> + 'static + Sync + Send,

Sets a callback which will be invoked just after the client’s hello message is received.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_set_client_hello_cb.

+
source

pub fn set_session_cache_size(&mut self, size: i32) -> i64

Sets the context’s session cache size limit, returning the previous limit.

+

A value of 0 means that the cache size is unbounded.

+

This corresponds to SSL_CTX_sess_set_cache_size.

+
source

pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack>

Sets the context’s supported signature algorithms.

+

Requires OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_set1_sigalgs_list.

+
source

pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack>

Sets the context’s supported elliptic curve groups.

+

Requires BoringSSL or OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer.

+

This corresponds to SSL_CTX_set1_groups_list.

+
source

pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack>

Sets the number of TLS 1.3 session tickets that will be sent to a client after a full +handshake.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_set_num_tickets.

+
source

pub fn set_security_level(&mut self, level: u32)

Set the context’s security level to a value between 0 and 5, inclusive. +A security value of 0 allows allows all parameters and algorithms.

+

Requires OpenSSL 1.1.0 or newer.

+

This corresponds to SSL_CTX_set_security_level.

+

Trait Implementations§

source§

impl Deref for SslAcceptorBuilder

source§

type Target = SslContextBuilder

The resulting type after dereferencing.
source§

fn deref(&self) -> &SslContextBuilder

Dereferences the value.
source§

impl DerefMut for SslAcceptorBuilder

source§

fn deref_mut(&mut self) -> &mut SslContextBuilder

Mutably dereferences the value.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/sidebar-items.js b/actix_tls/accept/openssl/sidebar-items.js new file mode 100644 index 00000000..609abc9a --- /dev/null +++ b/actix_tls/accept/openssl/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["Acceptor","AcceptorService","TlsStream"]}; \ No newline at end of file diff --git a/actix_tls/accept/openssl/struct.Acceptor.html b/actix_tls/accept/openssl/struct.Acceptor.html new file mode 100644 index 00000000..6ccb2872 --- /dev/null +++ b/actix_tls/accept/openssl/struct.Acceptor.html @@ -0,0 +1,38 @@ +Acceptor in actix_tls::accept::openssl - Rust
actix_tls::accept::openssl

Struct Acceptor

source
pub struct Acceptor { /* private fields */ }
Expand description

Accept TLS connections via the openssl crate.

+

Implementations§

source§

impl Acceptor

source

pub fn new(acceptor: SslAcceptor) -> Self

Create openssl based acceptor service factory.

+
source

pub fn set_handshake_timeout( + &mut self, + handshake_timeout: Duration, +) -> &mut Self

Limit the amount of time that the acceptor will wait for a TLS handshake to complete.

+

Default timeout is 3 seconds.

+

Trait Implementations§

source§

impl Clone for Acceptor

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<IO: ActixStream> ServiceFactory<IO> for Acceptor

source§

type Response = TlsStream<IO>

Responses given by the created services.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = AcceptorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Acceptor as ServiceFactory<IO>>::Service, <Acceptor as ServiceFactory<IO>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/struct.AcceptorService.html b/actix_tls/accept/openssl/struct.AcceptorService.html new file mode 100644 index 00000000..34367e5a --- /dev/null +++ b/actix_tls/accept/openssl/struct.AcceptorService.html @@ -0,0 +1,27 @@ +AcceptorService in actix_tls::accept::openssl - Rust
actix_tls::accept::openssl

Struct AcceptorService

source
pub struct AcceptorService { /* private fields */ }
Expand description

OpenSSL based acceptor service.

+

Trait Implementations§

source§

impl<IO: ActixStream> Service<IO> for AcceptorService

source§

type Response = TlsStream<IO>

Responses given by the service.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the service when polling readiness or executing call.
source§

type Future = AcceptFut<IO>

The future response value.
source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, io: IO) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/openssl/struct.TlsStream.html b/actix_tls/accept/openssl/struct.TlsStream.html new file mode 100644 index 00000000..b2d18506 --- /dev/null +++ b/actix_tls/accept/openssl/struct.TlsStream.html @@ -0,0 +1,83 @@ +TlsStream in actix_tls::accept::openssl - Rust
actix_tls::accept::openssl

Struct TlsStream

source
pub struct TlsStream<IO>(/* private fields */);
Expand description

Wraps an openssl based async TLS stream in order to implement [ActixStream].

+

Methods from Deref<Target = SslStream<IO>>§

pub fn poll_connect( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

pub async fn connect(self: Pin<&mut SslStream<S>>) -> Result<(), Error>

A convenience method wrapping poll_connect.

+

pub fn poll_accept( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

pub async fn accept(self: Pin<&mut SslStream<S>>) -> Result<(), Error>

A convenience method wrapping poll_accept.

+

pub fn poll_do_handshake( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

pub async fn do_handshake(self: Pin<&mut SslStream<S>>) -> Result<(), Error>

A convenience method wrapping poll_do_handshake.

+

pub fn poll_peek( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, + buf: &mut [u8], +) -> Poll<Result<usize, Error>>

pub async fn peek( + self: Pin<&mut SslStream<S>>, + buf: &mut [u8], +) -> Result<usize, Error>

A convenience method wrapping poll_peek.

+

pub fn poll_read_early_data( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, + buf: &mut [u8], +) -> Poll<Result<usize, Error>>

pub async fn read_early_data( + self: Pin<&mut SslStream<S>>, + buf: &mut [u8], +) -> Result<usize, Error>

A convenience method wrapping poll_read_early_data.

+

pub fn poll_write_early_data( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

pub async fn write_early_data( + self: Pin<&mut SslStream<S>>, + buf: &[u8], +) -> Result<usize, Error>

A convenience method wrapping poll_write_early_data.

+

pub fn ssl(&self) -> &SslRef

Returns a shared reference to the Ssl object associated with this stream.

+

pub fn get_ref(&self) -> &S

Returns a shared reference to the underlying stream.

+

pub fn get_mut(&mut self) -> &mut S

Returns a mutable reference to the underlying stream.

+

pub fn get_pin_mut(self: Pin<&mut SslStream<S>>) -> Pin<&mut S>

Returns a pinned mutable reference to the underlying stream.

+

Trait Implementations§

source§

impl<IO: ActixStream> AsyncRead for TlsStream<IO>

source§

fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<()>>

Attempts to read from the AsyncRead into buf. Read more
source§

impl<IO: ActixStream> AsyncWrite for TlsStream<IO>

source§

fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
source§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
source§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
source§

impl<IO> Deref for TlsStream<IO>

source§

type Target = SslStream<IO>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<IO> DerefMut for TlsStream<IO>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<IO> From<SslStream<IO>> for TlsStream<IO>

source§

fn from(from: SslStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>

§

impl<IO> RefUnwindSafe for TlsStream<IO>
where + IO: RefUnwindSafe,

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> UnwindSafe for TlsStream<IO>
where + IO: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/index.html b/actix_tls/accept/rustls_0_20/index.html new file mode 100644 index 00000000..2ece8553 --- /dev/null +++ b/actix_tls/accept/rustls_0_20/index.html @@ -0,0 +1,3 @@ +actix_tls::accept::rustls_0_20 - Rust
actix_tls::accept

Module rustls_0_20

source
Expand description

rustls v0.20 based TLS connection acceptor service.

+

See Acceptor for main service factory docs.

+

Modules§

  • Re-exports from rustls that are useful for acceptors.

Structs§

  • Accept TLS connections via the rustls crate.
  • Rustls based acceptor service.
  • Wraps a rustls based async TLS stream in order to implement [ActixStream].
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/reexports/index.html b/actix_tls/accept/rustls_0_20/reexports/index.html new file mode 100644 index 00000000..f061b746 --- /dev/null +++ b/actix_tls/accept/rustls_0_20/reexports/index.html @@ -0,0 +1,2 @@ +actix_tls::accept::rustls_0_20::reexports - Rust
actix_tls::accept::rustls_0_20

Module reexports

source
Expand description

Re-exports from rustls that are useful for acceptors.

+

Structs§

  • Common configuration for a set of server sessions.
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/reexports/sidebar-items.js b/actix_tls/accept/rustls_0_20/reexports/sidebar-items.js new file mode 100644 index 00000000..78a9f205 --- /dev/null +++ b/actix_tls/accept/rustls_0_20/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["ServerConfig"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/reexports/struct.ServerConfig.html b/actix_tls/accept/rustls_0_20/reexports/struct.ServerConfig.html new file mode 100644 index 00000000..3899d13a --- /dev/null +++ b/actix_tls/accept/rustls_0_20/reexports/struct.ServerConfig.html @@ -0,0 +1,82 @@ +ServerConfig in actix_tls::accept::rustls_0_20::reexports - Rust
actix_tls::accept::rustls_0_20::reexports

Struct ServerConfig

pub struct ServerConfig {
+    pub ignore_client_order: bool,
+    pub max_fragment_size: Option<usize>,
+    pub session_storage: Arc<dyn StoresServerSessions + Sync + Send>,
+    pub ticketer: Arc<dyn ProducesTickets>,
+    pub cert_resolver: Arc<dyn ResolvesServerCert>,
+    pub alpn_protocols: Vec<Vec<u8>>,
+    pub key_log: Arc<dyn KeyLog>,
+    pub max_early_data_size: u32,
+    pub send_half_rtt_data: bool,
+    /* private fields */
+}
Expand description

Common configuration for a set of server sessions.

+

Making one of these can be expensive, and should be +once per process rather than once per connection.

+

These must be created via the ServerConfig::builder() function.

+

§Defaults

+ +

Fields§

§ignore_client_order: bool

Ignore the client’s ciphersuite order. Instead, +choose the top ciphersuite in the server list +which is supported by the client.

+
§max_fragment_size: Option<usize>

The maximum size of TLS message we’ll emit. If None, we don’t limit TLS +message lengths except to the 2**16 limit specified in the standard.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ServerConnection::new.

+

Setting this value to the TCP MSS may improve latency for stream-y workloads.

+
§session_storage: Arc<dyn StoresServerSessions + Sync + Send>

How to store client sessions.

+
§ticketer: Arc<dyn ProducesTickets>

How to produce tickets.

+
§cert_resolver: Arc<dyn ResolvesServerCert>

How to choose a server cert and key.

+
§alpn_protocols: Vec<Vec<u8>>

Protocol names we support, most preferred first. +If empty we don’t do ALPN at all.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§max_early_data_size: u32

Amount of early data to accept for sessions created by +this config. Specify 0 to disable early data. The +default is 0.

+

Read the early data via [ServerConnection::early_data].

+

The units for this are both plaintext bytes, and ciphertext +bytes, depending on whether the server accepts a client’s early_data +or not. It is therefore recommended to include some slop in +this value to account for the unknown amount of ciphertext +expansion in the latter case.

+
§send_half_rtt_data: bool

Whether the server should send “0.5RTT” data. This means the server +sends data after its first flight of handshake messages, without +waiting for the client to complete the handshake.

+

This can improve TTFB latency for either server-speaks-first protocols, +or client-speaks-first protocols when paired with “0RTT” data. This +comes at the cost of a subtle weakening of the normal handshake +integrity guarantees that TLS provides. Note that the initial +ClientHello is indirectly authenticated because it is included +in the transcript used to derive the keys used to encrypt the data.

+

This only applies to TLS1.3 connections. TLS1.2 connections cannot +do this optimisation and this setting is ignored for them. It is +also ignored for TLS1.3 connections that even attempt client +authentication.

+

This defaults to false. This means the first application data +sent by the server comes after receiving and validating the client’s +handshake up to the Finished message. This is the safest option.

+

Implementations§

§

impl ServerConfig

pub fn builder() -> ConfigBuilder<ServerConfig, WantsCipherSuites>

Create builder to build up the server configuration.

+

For more information, see the [ConfigBuilder] documentation.

+

Trait Implementations§

§

impl Clone for ServerConfig

§

fn clone(&self) -> ServerConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ServerConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ServerConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/sidebar-items.js b/actix_tls/accept/rustls_0_20/sidebar-items.js new file mode 100644 index 00000000..609abc9a --- /dev/null +++ b/actix_tls/accept/rustls_0_20/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["Acceptor","AcceptorService","TlsStream"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/struct.Acceptor.html b/actix_tls/accept/rustls_0_20/struct.Acceptor.html new file mode 100644 index 00000000..557750ce --- /dev/null +++ b/actix_tls/accept/rustls_0_20/struct.Acceptor.html @@ -0,0 +1,38 @@ +Acceptor in actix_tls::accept::rustls_0_20 - Rust
actix_tls::accept::rustls_0_20

Struct Acceptor

source
pub struct Acceptor { /* private fields */ }
Expand description

Accept TLS connections via the rustls crate.

+

Implementations§

source§

impl Acceptor

source

pub fn new(config: ServerConfig) -> Self

Constructs rustls based acceptor service factory.

+
source

pub fn set_handshake_timeout( + &mut self, + handshake_timeout: Duration, +) -> &mut Self

Limit the amount of time that the acceptor will wait for a TLS handshake to complete.

+

Default timeout is 3 seconds.

+

Trait Implementations§

source§

impl Clone for Acceptor

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<IO: ActixStream> ServiceFactory<IO> for Acceptor

source§

type Response = TlsStream<IO>

Responses given by the created services.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = AcceptorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Acceptor as ServiceFactory<IO>>::Service, <Acceptor as ServiceFactory<IO>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/struct.AcceptorService.html b/actix_tls/accept/rustls_0_20/struct.AcceptorService.html new file mode 100644 index 00000000..1f9e99aa --- /dev/null +++ b/actix_tls/accept/rustls_0_20/struct.AcceptorService.html @@ -0,0 +1,27 @@ +AcceptorService in actix_tls::accept::rustls_0_20 - Rust
actix_tls::accept::rustls_0_20

Struct AcceptorService

source
pub struct AcceptorService { /* private fields */ }
Expand description

Rustls based acceptor service.

+

Trait Implementations§

source§

impl<IO: ActixStream> Service<IO> for AcceptorService

source§

type Response = TlsStream<IO>

Responses given by the service.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the service when polling readiness or executing call.
source§

type Future = AcceptFut<IO>

The future response value.
source§

fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: IO) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_20/struct.TlsStream.html b/actix_tls/accept/rustls_0_20/struct.TlsStream.html new file mode 100644 index 00000000..9a88d86f --- /dev/null +++ b/actix_tls/accept/rustls_0_20/struct.TlsStream.html @@ -0,0 +1,36 @@ +TlsStream in actix_tls::accept::rustls_0_20 - Rust
actix_tls::accept::rustls_0_20

Struct TlsStream

source
pub struct TlsStream<IO>(/* private fields */);
Expand description

Wraps a rustls based async TLS stream in order to implement [ActixStream].

+

Methods from Deref<Target = TlsStream<IO>>§

pub fn get_ref(&self) -> (&IO, &ServerConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ServerConnection)

Trait Implementations§

source§

impl<IO: ActixStream> AsyncRead for TlsStream<IO>

source§

fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<()>>

Attempts to read from the AsyncRead into buf. Read more
source§

impl<IO: ActixStream> AsyncWrite for TlsStream<IO>

source§

fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
source§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
source§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
source§

impl<IO> Deref for TlsStream<IO>

source§

type Target = TlsStream<IO>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<IO> DerefMut for TlsStream<IO>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<IO> From<TlsStream<IO>> for TlsStream<IO>

source§

fn from(from: TlsStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/index.html b/actix_tls/accept/rustls_0_21/index.html new file mode 100644 index 00000000..4387a220 --- /dev/null +++ b/actix_tls/accept/rustls_0_21/index.html @@ -0,0 +1,3 @@ +actix_tls::accept::rustls_0_21 - Rust
actix_tls::accept

Module rustls_0_21

source
Expand description

rustls v0.21 based TLS connection acceptor service.

+

See Acceptor for main service factory docs.

+

Modules§

  • Re-exports from rustls that are useful for acceptors.

Structs§

  • Accept TLS connections via the rustls crate.
  • Rustls based acceptor service.
  • Wraps a rustls based async TLS stream in order to implement [ActixStream].
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/reexports/index.html b/actix_tls/accept/rustls_0_21/reexports/index.html new file mode 100644 index 00000000..fb0eaf6e --- /dev/null +++ b/actix_tls/accept/rustls_0_21/reexports/index.html @@ -0,0 +1,2 @@ +actix_tls::accept::rustls_0_21::reexports - Rust
actix_tls::accept::rustls_0_21

Module reexports

source
Expand description

Re-exports from rustls that are useful for acceptors.

+

Structs§

  • Common configuration for a set of server sessions.
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/reexports/sidebar-items.js b/actix_tls/accept/rustls_0_21/reexports/sidebar-items.js new file mode 100644 index 00000000..78a9f205 --- /dev/null +++ b/actix_tls/accept/rustls_0_21/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["ServerConfig"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/reexports/struct.ServerConfig.html b/actix_tls/accept/rustls_0_21/reexports/struct.ServerConfig.html new file mode 100644 index 00000000..76b861dc --- /dev/null +++ b/actix_tls/accept/rustls_0_21/reexports/struct.ServerConfig.html @@ -0,0 +1,92 @@ +ServerConfig in actix_tls::accept::rustls_0_21::reexports - Rust
actix_tls::accept::rustls_0_21::reexports

Struct ServerConfig

pub struct ServerConfig {
+    pub ignore_client_order: bool,
+    pub max_fragment_size: Option<usize>,
+    pub session_storage: Arc<dyn StoresServerSessions + Sync + Send>,
+    pub ticketer: Arc<dyn ProducesTickets>,
+    pub cert_resolver: Arc<dyn ResolvesServerCert>,
+    pub alpn_protocols: Vec<Vec<u8>>,
+    pub key_log: Arc<dyn KeyLog>,
+    pub max_early_data_size: u32,
+    pub send_half_rtt_data: bool,
+    pub send_tls13_tickets: usize,
+    /* private fields */
+}
Expand description

Common configuration for a set of server sessions.

+

Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots +from the operating system to add to the RootCertStore passed to a ClientCertVerifier +builder may take on the order of a few hundred milliseconds.

+

These must be created via the ServerConfig::builder() function.

+

§Defaults

+ +

Fields§

§ignore_client_order: bool

Ignore the client’s ciphersuite order. Instead, +choose the top ciphersuite in the server list +which is supported by the client.

+
§max_fragment_size: Option<usize>

The maximum size of TLS message we’ll emit. If None, we don’t limit TLS +message lengths except to the 2**16 limit specified in the standard.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ServerConnection::new.

+

Setting this value to the TCP MSS may improve latency for stream-y workloads.

+
§session_storage: Arc<dyn StoresServerSessions + Sync + Send>

How to store client sessions.

+
§ticketer: Arc<dyn ProducesTickets>

How to produce tickets.

+
§cert_resolver: Arc<dyn ResolvesServerCert>

How to choose a server cert and key.

+
§alpn_protocols: Vec<Vec<u8>>

Protocol names we support, most preferred first. +If empty we don’t do ALPN at all.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§max_early_data_size: u32

Amount of early data to accept for sessions created by +this config. Specify 0 to disable early data. The +default is 0.

+

Read the early data via [ServerConnection::early_data].

+

The units for this are both plaintext bytes, and ciphertext +bytes, depending on whether the server accepts a client’s early_data +or not. It is therefore recommended to include some slop in +this value to account for the unknown amount of ciphertext +expansion in the latter case.

+
§send_half_rtt_data: bool

Whether the server should send “0.5RTT” data. This means the server +sends data after its first flight of handshake messages, without +waiting for the client to complete the handshake.

+

This can improve TTFB latency for either server-speaks-first protocols, +or client-speaks-first protocols when paired with “0RTT” data. This +comes at the cost of a subtle weakening of the normal handshake +integrity guarantees that TLS provides. Note that the initial +ClientHello is indirectly authenticated because it is included +in the transcript used to derive the keys used to encrypt the data.

+

This only applies to TLS1.3 connections. TLS1.2 connections cannot +do this optimisation and this setting is ignored for them. It is +also ignored for TLS1.3 connections that even attempt client +authentication.

+

This defaults to false. This means the first application data +sent by the server comes after receiving and validating the client’s +handshake up to the Finished message. This is the safest option.

+
§send_tls13_tickets: usize

How many TLS1.3 tickets to send immediately after a successful +handshake.

+

Because TLS1.3 tickets are single-use, this allows +a client to perform multiple resumptions.

+

The default is 4.

+

If this is 0, no tickets are sent and clients will not be able to +do any resumption.

+

Implementations§

§

impl ServerConfig

pub fn builder() -> ConfigBuilder<ServerConfig, WantsCipherSuites>

Create builder to build up the server configuration.

+

For more information, see the [ConfigBuilder] documentation.

+

Trait Implementations§

§

impl Clone for ServerConfig

§

fn clone(&self) -> ServerConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ServerConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ServerConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/sidebar-items.js b/actix_tls/accept/rustls_0_21/sidebar-items.js new file mode 100644 index 00000000..609abc9a --- /dev/null +++ b/actix_tls/accept/rustls_0_21/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["Acceptor","AcceptorService","TlsStream"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/struct.Acceptor.html b/actix_tls/accept/rustls_0_21/struct.Acceptor.html new file mode 100644 index 00000000..8664004c --- /dev/null +++ b/actix_tls/accept/rustls_0_21/struct.Acceptor.html @@ -0,0 +1,38 @@ +Acceptor in actix_tls::accept::rustls_0_21 - Rust
actix_tls::accept::rustls_0_21

Struct Acceptor

source
pub struct Acceptor { /* private fields */ }
Expand description

Accept TLS connections via the rustls crate.

+

Implementations§

source§

impl Acceptor

source

pub fn new(config: ServerConfig) -> Self

Constructs rustls based acceptor service factory.

+
source

pub fn set_handshake_timeout( + &mut self, + handshake_timeout: Duration, +) -> &mut Self

Limit the amount of time that the acceptor will wait for a TLS handshake to complete.

+

Default timeout is 3 seconds.

+

Trait Implementations§

source§

impl Clone for Acceptor

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<IO: ActixStream> ServiceFactory<IO> for Acceptor

source§

type Response = TlsStream<IO>

Responses given by the created services.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = AcceptorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Acceptor as ServiceFactory<IO>>::Service, <Acceptor as ServiceFactory<IO>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/struct.AcceptorService.html b/actix_tls/accept/rustls_0_21/struct.AcceptorService.html new file mode 100644 index 00000000..be726287 --- /dev/null +++ b/actix_tls/accept/rustls_0_21/struct.AcceptorService.html @@ -0,0 +1,27 @@ +AcceptorService in actix_tls::accept::rustls_0_21 - Rust
actix_tls::accept::rustls_0_21

Struct AcceptorService

source
pub struct AcceptorService { /* private fields */ }
Expand description

Rustls based acceptor service.

+

Trait Implementations§

source§

impl<IO: ActixStream> Service<IO> for AcceptorService

source§

type Response = TlsStream<IO>

Responses given by the service.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the service when polling readiness or executing call.
source§

type Future = AcceptFut<IO>

The future response value.
source§

fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: IO) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_21/struct.TlsStream.html b/actix_tls/accept/rustls_0_21/struct.TlsStream.html new file mode 100644 index 00000000..d42b0c07 --- /dev/null +++ b/actix_tls/accept/rustls_0_21/struct.TlsStream.html @@ -0,0 +1,36 @@ +TlsStream in actix_tls::accept::rustls_0_21 - Rust
actix_tls::accept::rustls_0_21

Struct TlsStream

source
pub struct TlsStream<IO>(/* private fields */);
Expand description

Wraps a rustls based async TLS stream in order to implement [ActixStream].

+

Methods from Deref<Target = TlsStream<IO>>§

pub fn get_ref(&self) -> (&IO, &ServerConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ServerConnection)

Trait Implementations§

source§

impl<IO: ActixStream> AsyncRead for TlsStream<IO>

source§

fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<()>>

Attempts to read from the AsyncRead into buf. Read more
source§

impl<IO: ActixStream> AsyncWrite for TlsStream<IO>

source§

fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
source§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
source§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
source§

impl<IO> Deref for TlsStream<IO>

source§

type Target = TlsStream<IO>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<IO> DerefMut for TlsStream<IO>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<IO> From<TlsStream<IO>> for TlsStream<IO>

source§

fn from(from: TlsStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/index.html b/actix_tls/accept/rustls_0_22/index.html new file mode 100644 index 00000000..4836e57d --- /dev/null +++ b/actix_tls/accept/rustls_0_22/index.html @@ -0,0 +1,3 @@ +actix_tls::accept::rustls_0_22 - Rust
actix_tls::accept

Module rustls_0_22

source
Expand description

rustls v0.22 based TLS connection acceptor service.

+

See Acceptor for main service factory docs.

+

Modules§

  • Re-exports from rustls that are useful for acceptors.

Structs§

  • Accept TLS connections via the rustls crate.
  • Rustls based acceptor service.
  • Wraps a rustls based async TLS stream in order to implement [ActixStream].
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/reexports/index.html b/actix_tls/accept/rustls_0_22/reexports/index.html new file mode 100644 index 00000000..84b51d54 --- /dev/null +++ b/actix_tls/accept/rustls_0_22/reexports/index.html @@ -0,0 +1,2 @@ +actix_tls::accept::rustls_0_22::reexports - Rust
actix_tls::accept::rustls_0_22

Module reexports

source
Expand description

Re-exports from rustls that are useful for acceptors.

+

Structs§

  • Common configuration for a set of server sessions.
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/reexports/sidebar-items.js b/actix_tls/accept/rustls_0_22/reexports/sidebar-items.js new file mode 100644 index 00000000..78a9f205 --- /dev/null +++ b/actix_tls/accept/rustls_0_22/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["ServerConfig"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/reexports/struct.ServerConfig.html b/actix_tls/accept/rustls_0_22/reexports/struct.ServerConfig.html new file mode 100644 index 00000000..7cdb7647 --- /dev/null +++ b/actix_tls/accept/rustls_0_22/reexports/struct.ServerConfig.html @@ -0,0 +1,116 @@ +ServerConfig in actix_tls::accept::rustls_0_22::reexports - Rust
actix_tls::accept::rustls_0_22::reexports

Struct ServerConfig

pub struct ServerConfig {
+    pub ignore_client_order: bool,
+    pub max_fragment_size: Option<usize>,
+    pub session_storage: Arc<dyn StoresServerSessions + Sync + Send>,
+    pub ticketer: Arc<dyn ProducesTickets>,
+    pub cert_resolver: Arc<dyn ResolvesServerCert>,
+    pub alpn_protocols: Vec<Vec<u8>>,
+    pub key_log: Arc<dyn KeyLog>,
+    pub enable_secret_extraction: bool,
+    pub max_early_data_size: u32,
+    pub send_half_rtt_data: bool,
+    pub send_tls13_tickets: usize,
+    /* private fields */
+}
Expand description

Common configuration for a set of server sessions.

+

Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots +from the operating system to add to the RootCertStore passed to a ClientCertVerifier +builder may take on the order of a few hundred milliseconds.

+

These must be created via the ServerConfig::builder() or ServerConfig::builder_with_provider() +function.

+

§Defaults

+ +

Fields§

§ignore_client_order: bool

Ignore the client’s ciphersuite order. Instead, +choose the top ciphersuite in the server list +which is supported by the client.

+
§max_fragment_size: Option<usize>

The maximum size of plaintext input to be emitted in a single TLS record. +A value of None is equivalent to the TLS maximum of 16 kB.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ServerConnection::new.

+

Setting this value to a little less than the TCP MSS may improve latency +for stream-y workloads.

+
§session_storage: Arc<dyn StoresServerSessions + Sync + Send>

How to store client sessions.

+
§ticketer: Arc<dyn ProducesTickets>

How to produce tickets.

+
§cert_resolver: Arc<dyn ResolvesServerCert>

How to choose a server cert and key. This is usually set by +[ConfigBuilder::with_single_cert] or [ConfigBuilder::with_cert_resolver]. +For async applications, see also [Acceptor].

+
§alpn_protocols: Vec<Vec<u8>>

Protocol names we support, most preferred first. +If empty we don’t do ALPN at all.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§enable_secret_extraction: bool

Allows traffic secrets to be extracted after the handshake, +e.g. for kTLS setup.

+
§max_early_data_size: u32

Amount of early data to accept for sessions created by +this config. Specify 0 to disable early data. The +default is 0.

+

Read the early data via [ServerConnection::early_data].

+

The units for this are both plaintext bytes, and ciphertext +bytes, depending on whether the server accepts a client’s early_data +or not. It is therefore recommended to include some slop in +this value to account for the unknown amount of ciphertext +expansion in the latter case.

+
§send_half_rtt_data: bool

Whether the server should send “0.5RTT” data. This means the server +sends data after its first flight of handshake messages, without +waiting for the client to complete the handshake.

+

This can improve TTFB latency for either server-speaks-first protocols, +or client-speaks-first protocols when paired with “0RTT” data. This +comes at the cost of a subtle weakening of the normal handshake +integrity guarantees that TLS provides. Note that the initial +ClientHello is indirectly authenticated because it is included +in the transcript used to derive the keys used to encrypt the data.

+

This only applies to TLS1.3 connections. TLS1.2 connections cannot +do this optimisation and this setting is ignored for them. It is +also ignored for TLS1.3 connections that even attempt client +authentication.

+

This defaults to false. This means the first application data +sent by the server comes after receiving and validating the client’s +handshake up to the Finished message. This is the safest option.

+
§send_tls13_tickets: usize

How many TLS1.3 tickets to send immediately after a successful +handshake.

+

Because TLS1.3 tickets are single-use, this allows +a client to perform multiple resumptions.

+

The default is 4.

+

If this is 0, no tickets are sent and clients will not be able to +do any resumption.

+

Implementations§

§

impl ServerConfig

pub fn builder() -> ConfigBuilder<ServerConfig, WantsVerifier>

Create a builder for a server configuration with the default +[CryptoProvider]: [crypto::ring::default_provider] and safe ciphersuite and protocol +defaults.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_protocol_versions( + versions: &[&'static SupportedProtocolVersion], +) -> ConfigBuilder<ServerConfig, WantsVerifier>

Create a builder for a server configuration with the default +[CryptoProvider]: [crypto::ring::default_provider], safe ciphersuite defaults and +the provided protocol versions.

+

Panics if provided an empty slice of supported versions.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_provider( + provider: Arc<CryptoProvider>, +) -> ConfigBuilder<ServerConfig, WantsVersions>

Create a builder for a server configuration with a specific [CryptoProvider].

+

This will use the provider’s configured ciphersuites. You must additionally choose +which protocol versions to enable, using with_protocol_versions or +with_safe_default_protocol_versions and handling the Result in case a protocol +version is not supported by the provider’s ciphersuites.

+

For more information, see the [ConfigBuilder] documentation.

+

Trait Implementations§

§

impl Clone for ServerConfig

§

fn clone(&self) -> ServerConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ServerConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ServerConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/sidebar-items.js b/actix_tls/accept/rustls_0_22/sidebar-items.js new file mode 100644 index 00000000..609abc9a --- /dev/null +++ b/actix_tls/accept/rustls_0_22/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["Acceptor","AcceptorService","TlsStream"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/struct.Acceptor.html b/actix_tls/accept/rustls_0_22/struct.Acceptor.html new file mode 100644 index 00000000..1c3c65dc --- /dev/null +++ b/actix_tls/accept/rustls_0_22/struct.Acceptor.html @@ -0,0 +1,38 @@ +Acceptor in actix_tls::accept::rustls_0_22 - Rust
actix_tls::accept::rustls_0_22

Struct Acceptor

source
pub struct Acceptor { /* private fields */ }
Expand description

Accept TLS connections via the rustls crate.

+

Implementations§

source§

impl Acceptor

source

pub fn new(config: ServerConfig) -> Self

Constructs rustls based acceptor service factory.

+
source

pub fn set_handshake_timeout( + &mut self, + handshake_timeout: Duration, +) -> &mut Self

Limit the amount of time that the acceptor will wait for a TLS handshake to complete.

+

Default timeout is 3 seconds.

+

Trait Implementations§

source§

impl Clone for Acceptor

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<IO: ActixStream> ServiceFactory<IO> for Acceptor

source§

type Response = TlsStream<IO>

Responses given by the created services.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = AcceptorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Acceptor as ServiceFactory<IO>>::Service, <Acceptor as ServiceFactory<IO>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/struct.AcceptorService.html b/actix_tls/accept/rustls_0_22/struct.AcceptorService.html new file mode 100644 index 00000000..8fc3e67b --- /dev/null +++ b/actix_tls/accept/rustls_0_22/struct.AcceptorService.html @@ -0,0 +1,27 @@ +AcceptorService in actix_tls::accept::rustls_0_22 - Rust
actix_tls::accept::rustls_0_22

Struct AcceptorService

source
pub struct AcceptorService { /* private fields */ }
Expand description

Rustls based acceptor service.

+

Trait Implementations§

source§

impl<IO: ActixStream> Service<IO> for AcceptorService

source§

type Response = TlsStream<IO>

Responses given by the service.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the service when polling readiness or executing call.
source§

type Future = AcceptFut<IO>

The future response value.
source§

fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: IO) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_22/struct.TlsStream.html b/actix_tls/accept/rustls_0_22/struct.TlsStream.html new file mode 100644 index 00000000..5a39a32b --- /dev/null +++ b/actix_tls/accept/rustls_0_22/struct.TlsStream.html @@ -0,0 +1,36 @@ +TlsStream in actix_tls::accept::rustls_0_22 - Rust
actix_tls::accept::rustls_0_22

Struct TlsStream

source
pub struct TlsStream<IO>(/* private fields */);
Expand description

Wraps a rustls based async TLS stream in order to implement [ActixStream].

+

Methods from Deref<Target = TlsStream<IO>>§

pub fn get_ref(&self) -> (&IO, &ServerConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ServerConnection)

Trait Implementations§

source§

impl<IO: ActixStream> AsyncRead for TlsStream<IO>

source§

fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<()>>

Attempts to read from the AsyncRead into buf. Read more
source§

impl<IO: ActixStream> AsyncWrite for TlsStream<IO>

source§

fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
source§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
source§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
source§

impl<IO> Deref for TlsStream<IO>

source§

type Target = TlsStream<IO>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<IO> DerefMut for TlsStream<IO>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<IO> From<TlsStream<IO>> for TlsStream<IO>

source§

fn from(from: TlsStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/index.html b/actix_tls/accept/rustls_0_23/index.html new file mode 100644 index 00000000..cec45f13 --- /dev/null +++ b/actix_tls/accept/rustls_0_23/index.html @@ -0,0 +1,3 @@ +actix_tls::accept::rustls_0_23 - Rust
actix_tls::accept

Module rustls_0_23

source
Expand description

rustls v0.23 based TLS connection acceptor service.

+

See Acceptor for main service factory docs.

+

Modules§

  • Re-exports from rustls that are useful for acceptors.

Structs§

  • Accept TLS connections via the rustls crate.
  • Rustls based acceptor service.
  • Wraps a rustls based async TLS stream in order to implement [ActixStream].
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/reexports/index.html b/actix_tls/accept/rustls_0_23/reexports/index.html new file mode 100644 index 00000000..8f451706 --- /dev/null +++ b/actix_tls/accept/rustls_0_23/reexports/index.html @@ -0,0 +1,2 @@ +actix_tls::accept::rustls_0_23::reexports - Rust
actix_tls::accept::rustls_0_23

Module reexports

source
Expand description

Re-exports from rustls that are useful for acceptors.

+

Structs§

  • Common configuration for a set of server sessions.
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/reexports/sidebar-items.js b/actix_tls/accept/rustls_0_23/reexports/sidebar-items.js new file mode 100644 index 00000000..78a9f205 --- /dev/null +++ b/actix_tls/accept/rustls_0_23/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["ServerConfig"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/reexports/struct.ServerConfig.html b/actix_tls/accept/rustls_0_23/reexports/struct.ServerConfig.html new file mode 100644 index 00000000..375dd457 --- /dev/null +++ b/actix_tls/accept/rustls_0_23/reexports/struct.ServerConfig.html @@ -0,0 +1,169 @@ +ServerConfig in actix_tls::accept::rustls_0_23::reexports - Rust
actix_tls::accept::rustls_0_23::reexports

Struct ServerConfig

pub struct ServerConfig {
Show 15 fields + pub ignore_client_order: bool, + pub max_fragment_size: Option<usize>, + pub session_storage: Arc<dyn StoresServerSessions>, + pub ticketer: Arc<dyn ProducesTickets>, + pub cert_resolver: Arc<dyn ResolvesServerCert>, + pub alpn_protocols: Vec<Vec<u8>>, + pub key_log: Arc<dyn KeyLog>, + pub enable_secret_extraction: bool, + pub max_early_data_size: u32, + pub send_half_rtt_data: bool, + pub send_tls13_tickets: usize, + pub time_provider: Arc<dyn TimeProvider>, + pub cert_compressors: Vec<&'static dyn CertCompressor>, + pub cert_compression_cache: Arc<CompressionCache>, + pub cert_decompressors: Vec<&'static dyn CertDecompressor>, + /* private fields */ +
}
Expand description

Common configuration for a set of server sessions.

+

Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots +from the operating system to add to the RootCertStore passed to a ClientCertVerifier +builder may take on the order of a few hundred milliseconds.

+

These must be created via the ServerConfig::builder() or ServerConfig::builder_with_provider() +function.

+

§Defaults

+ +

Fields§

§ignore_client_order: bool

Ignore the client’s ciphersuite order. Instead, +choose the top ciphersuite in the server list +which is supported by the client.

+
§max_fragment_size: Option<usize>

The maximum size of plaintext input to be emitted in a single TLS record. +A value of None is equivalent to the TLS maximum of 16 kB.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ServerConnection::new.

+

Setting this value to a little less than the TCP MSS may improve latency +for stream-y workloads.

+
§session_storage: Arc<dyn StoresServerSessions>

How to store client sessions.

+
§ticketer: Arc<dyn ProducesTickets>

How to produce tickets.

+
§cert_resolver: Arc<dyn ResolvesServerCert>

How to choose a server cert and key. This is usually set by +[ConfigBuilder::with_single_cert] or [ConfigBuilder::with_cert_resolver]. +For async applications, see also [Acceptor].

+
§alpn_protocols: Vec<Vec<u8>>

Protocol names we support, most preferred first. +If empty we don’t do ALPN at all.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§enable_secret_extraction: bool

Allows traffic secrets to be extracted after the handshake, +e.g. for kTLS setup.

+
§max_early_data_size: u32

Amount of early data to accept for sessions created by +this config. Specify 0 to disable early data. The +default is 0.

+

Read the early data via [ServerConnection::early_data].

+

The units for this are both plaintext bytes, and ciphertext +bytes, depending on whether the server accepts a client’s early_data +or not. It is therefore recommended to include some slop in +this value to account for the unknown amount of ciphertext +expansion in the latter case.

+
§send_half_rtt_data: bool

Whether the server should send “0.5RTT” data. This means the server +sends data after its first flight of handshake messages, without +waiting for the client to complete the handshake.

+

This can improve TTFB latency for either server-speaks-first protocols, +or client-speaks-first protocols when paired with “0RTT” data. This +comes at the cost of a subtle weakening of the normal handshake +integrity guarantees that TLS provides. Note that the initial +ClientHello is indirectly authenticated because it is included +in the transcript used to derive the keys used to encrypt the data.

+

This only applies to TLS1.3 connections. TLS1.2 connections cannot +do this optimisation and this setting is ignored for them. It is +also ignored for TLS1.3 connections that even attempt client +authentication.

+

This defaults to false. This means the first application data +sent by the server comes after receiving and validating the client’s +handshake up to the Finished message. This is the safest option.

+
§send_tls13_tickets: usize

How many TLS1.3 tickets to send immediately after a successful +handshake.

+

Because TLS1.3 tickets are single-use, this allows +a client to perform multiple resumptions.

+

The default is 4.

+

If this is 0, no tickets are sent and clients will not be able to +do any resumption.

+
§time_provider: Arc<dyn TimeProvider>

Provides the current system time

+
§cert_compressors: Vec<&'static dyn CertCompressor>

How to compress the server’s certificate chain.

+

If a client supports this extension, and advertises support +for one of the compression algorithms included here, the +server certificate will be compressed according to RFC8779.

+

This only applies to TLS1.3 connections. It is ignored for +TLS1.2 connections.

+
§cert_compression_cache: Arc<CompressionCache>

Caching for compressed certificates.

+

This is optional: [compress::CompressionCache::Disabled] gives +a cache that does no caching.

+
§cert_decompressors: Vec<&'static dyn CertDecompressor>

How to decompress the clients’s certificate chain.

+

If this is non-empty, the RFC8779 certificate compression +extension is offered when requesting client authentication, +and any compressed certificates are transparently decompressed +during the handshake.

+

This only applies to TLS1.3 connections. It is ignored for +TLS1.2 connections.

+

Implementations§

§

impl ServerConfig

pub fn builder() -> ConfigBuilder<ServerConfig, WantsVerifier>

Create a builder for a server configuration with +[the process-default CryptoProvider][CryptoProvider#using-the-per-process-default-cryptoprovider] +and safe protocol version defaults.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_protocol_versions( + versions: &[&'static SupportedProtocolVersion], +) -> ConfigBuilder<ServerConfig, WantsVerifier>

Create a builder for a server configuration with +[the process-default CryptoProvider][CryptoProvider#using-the-per-process-default-cryptoprovider] +and the provided protocol versions.

+

Panics if

+
    +
  • the supported versions are not compatible with the provider (eg. +the combination of ciphersuites supported by the provider and supported +versions lead to zero cipher suites being usable),
  • +
  • if a CryptoProvider cannot be resolved using a combination of +the crate features and process default.
  • +
+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_provider( + provider: Arc<CryptoProvider>, +) -> ConfigBuilder<ServerConfig, WantsVersions>

Create a builder for a server configuration with a specific [CryptoProvider].

+

This will use the provider’s configured ciphersuites. You must additionally choose +which protocol versions to enable, using with_protocol_versions or +with_safe_default_protocol_versions and handling the Result in case a protocol +version is not supported by the provider’s ciphersuites.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_details( + provider: Arc<CryptoProvider>, + time_provider: Arc<dyn TimeProvider>, +) -> ConfigBuilder<ServerConfig, WantsVersions>

Create a builder for a server configuration with no default implementation details.

+

This API must be used by no_std users.

+

You must provide a specific [TimeProvider].

+

You must provide a specific [CryptoProvider].

+

This will use the provider’s configured ciphersuites. You must additionally choose +which protocol versions to enable, using with_protocol_versions or +with_safe_default_protocol_versions and handling the Result in case a protocol +version is not supported by the provider’s ciphersuites.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn fips(&self) -> bool

Return true if connections made with this ServerConfig will +operate in FIPS mode.

+

This is different from [CryptoProvider::fips()]: [CryptoProvider::fips()] +is concerned only with cryptography, whereas this also covers TLS-level +configuration that NIST recommends.

+

pub fn crypto_provider(&self) -> &Arc<CryptoProvider>

Return the crypto provider used to construct this client configuration.

+

Trait Implementations§

§

impl Clone for ServerConfig

§

fn clone(&self) -> ServerConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ServerConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ServerConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/sidebar-items.js b/actix_tls/accept/rustls_0_23/sidebar-items.js new file mode 100644 index 00000000..609abc9a --- /dev/null +++ b/actix_tls/accept/rustls_0_23/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["Acceptor","AcceptorService","TlsStream"]}; \ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/struct.Acceptor.html b/actix_tls/accept/rustls_0_23/struct.Acceptor.html new file mode 100644 index 00000000..d8f56161 --- /dev/null +++ b/actix_tls/accept/rustls_0_23/struct.Acceptor.html @@ -0,0 +1,38 @@ +Acceptor in actix_tls::accept::rustls_0_23 - Rust
actix_tls::accept::rustls_0_23

Struct Acceptor

source
pub struct Acceptor { /* private fields */ }
Expand description

Accept TLS connections via the rustls crate.

+

Implementations§

source§

impl Acceptor

source

pub fn new(config: ServerConfig) -> Self

Constructs rustls based acceptor service factory.

+
source

pub fn set_handshake_timeout( + &mut self, + handshake_timeout: Duration, +) -> &mut Self

Limit the amount of time that the acceptor will wait for a TLS handshake to complete.

+

Default timeout is 3 seconds.

+

Trait Implementations§

source§

impl Clone for Acceptor

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<IO: ActixStream> ServiceFactory<IO> for Acceptor

source§

type Response = TlsStream<IO>

Responses given by the created services.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = AcceptorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Acceptor as ServiceFactory<IO>>::Service, <Acceptor as ServiceFactory<IO>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/struct.AcceptorService.html b/actix_tls/accept/rustls_0_23/struct.AcceptorService.html new file mode 100644 index 00000000..70451f90 --- /dev/null +++ b/actix_tls/accept/rustls_0_23/struct.AcceptorService.html @@ -0,0 +1,27 @@ +AcceptorService in actix_tls::accept::rustls_0_23 - Rust
actix_tls::accept::rustls_0_23

Struct AcceptorService

source
pub struct AcceptorService { /* private fields */ }
Expand description

Rustls based acceptor service.

+

Trait Implementations§

source§

impl<IO: ActixStream> Service<IO> for AcceptorService

source§

type Response = TlsStream<IO>

Responses given by the service.
source§

type Error = TlsError<Error, Infallible>

Errors produced by the service when polling readiness or executing call.
source§

type Future = AcceptFut<IO>

The future response value.
source§

fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: IO) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/rustls_0_23/struct.TlsStream.html b/actix_tls/accept/rustls_0_23/struct.TlsStream.html new file mode 100644 index 00000000..a29ec06f --- /dev/null +++ b/actix_tls/accept/rustls_0_23/struct.TlsStream.html @@ -0,0 +1,36 @@ +TlsStream in actix_tls::accept::rustls_0_23 - Rust
actix_tls::accept::rustls_0_23

Struct TlsStream

source
pub struct TlsStream<IO>(/* private fields */);
Expand description

Wraps a rustls based async TLS stream in order to implement [ActixStream].

+

Methods from Deref<Target = TlsStream<IO>>§

pub fn get_ref(&self) -> (&IO, &ServerConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ServerConnection)

Trait Implementations§

source§

impl<IO: ActixStream> AsyncRead for TlsStream<IO>

source§

fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<()>>

Attempts to read from the AsyncRead into buf. Read more
source§

impl<IO: ActixStream> AsyncWrite for TlsStream<IO>

source§

fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
source§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
source§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
source§

impl<IO> Deref for TlsStream<IO>

source§

type Target = TlsStream<IO>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<IO> DerefMut for TlsStream<IO>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<IO> From<TlsStream<IO>> for TlsStream<IO>

source§

fn from(from: TlsStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/accept/sidebar-items.js b/actix_tls/accept/sidebar-items.js new file mode 100644 index 00000000..b946eaf8 --- /dev/null +++ b/actix_tls/accept/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["TlsError"],"fn":["max_concurrent_tls_connect"],"mod":["native_tls","openssl","rustls_0_20","rustls_0_21","rustls_0_22","rustls_0_23"]}; \ No newline at end of file diff --git a/actix_tls/all.html b/actix_tls/all.html new file mode 100644 index 00000000..8c9c3e15 --- /dev/null +++ b/actix_tls/all.html @@ -0,0 +1 @@ +List of all items in this crate

List of all items

Structs

Enums

Traits

Functions

Statics

Constants

\ No newline at end of file diff --git a/actix_tls/connect/connection/struct.Connection.html b/actix_tls/connect/connection/struct.Connection.html new file mode 100644 index 00000000..1fca3fcc --- /dev/null +++ b/actix_tls/connect/connection/struct.Connection.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/struct.Connection.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/connector/struct.Connector.html b/actix_tls/connect/connector/struct.Connector.html new file mode 100644 index 00000000..7ed48d92 --- /dev/null +++ b/actix_tls/connect/connector/struct.Connector.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/struct.Connector.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/connector/struct.ConnectorService.html b/actix_tls/connect/connector/struct.ConnectorService.html new file mode 100644 index 00000000..022ca935 --- /dev/null +++ b/actix_tls/connect/connector/struct.ConnectorService.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/struct.ConnectorService.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/enum.ConnectError.html b/actix_tls/connect/enum.ConnectError.html new file mode 100644 index 00000000..8de8dd8f --- /dev/null +++ b/actix_tls/connect/enum.ConnectError.html @@ -0,0 +1,29 @@ +ConnectError in actix_tls::connect - Rust
actix_tls::connect

Enum ConnectError

source
pub enum ConnectError {
+    Resolver(Box<dyn Error>),
+    NoRecords,
+    InvalidInput,
+    Unresolved,
+    Io(Error),
+}
Expand description

Errors that can result from using a connector service.

+

Variants§

§

Resolver(Box<dyn Error>)

Failed to resolve the hostname.

+
§

NoRecords

No DNS records.

+
§

InvalidInput

Invalid input.

+
§

Unresolved

Unresolved host name.

+
§

Io(Error)

Connection IO error.

+

Trait Implementations§

source§

impl Debug for ConnectError

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for ConnectError

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Error for ConnectError

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/error/enum.ConnectError.html b/actix_tls/connect/error/enum.ConnectError.html new file mode 100644 index 00000000..392e34ff --- /dev/null +++ b/actix_tls/connect/error/enum.ConnectError.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/enum.ConnectError.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/host/trait.Host.html b/actix_tls/connect/host/trait.Host.html new file mode 100644 index 00000000..d28ee925 --- /dev/null +++ b/actix_tls/connect/host/trait.Host.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/trait.Host.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/index.html b/actix_tls/connect/index.html new file mode 100644 index 00000000..92a67e8a --- /dev/null +++ b/actix_tls/connect/index.html @@ -0,0 +1,13 @@ +actix_tls::connect - Rust
actix_tls

Module connect

source
Expand description

TCP and TLS connector services.

+

§Stages of the TCP connector service:

+
    +
  1. Resolve Host (if needed) with given Resolver and collect list of socket addresses.
  2. +
  3. Establish TCP connection and return TcpStream.
  4. +
+

§Stages of TLS connector services:

+
    +
  1. Resolve DNS and establish a TcpStream with the TCP connector service.
  2. +
  3. Wrap the stream and perform connect handshake with remote peer.
  4. +
  5. Return wrapped stream type that implements AsyncRead and AsyncWrite.
  6. +
+

Modules§

Structs§

Enums§

  • Errors that can result from using a connector service.

Traits§

  • An interface for types where host parts (hostname and port) can be derived.
  • Custom async DNS resolvers.
\ No newline at end of file diff --git a/actix_tls/connect/info/struct.ConnectInfo.html b/actix_tls/connect/info/struct.ConnectInfo.html new file mode 100644 index 00000000..e507967c --- /dev/null +++ b/actix_tls/connect/info/struct.ConnectInfo.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/struct.ConnectInfo.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/native_tls/index.html b/actix_tls/connect/native_tls/index.html new file mode 100644 index 00000000..1889dacf --- /dev/null +++ b/actix_tls/connect/native_tls/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::native_tls - Rust
actix_tls::connect

Module native_tls

source
Expand description

Native-TLS based connector service.

+

See TlsConnector for main connector service factory docs.

+

Modules§

  • Re-exports from native-tls and tokio-native-tls that are useful for connectors.

Structs§

\ No newline at end of file diff --git a/actix_tls/connect/native_tls/reexports/index.html b/actix_tls/connect/native_tls/reexports/index.html new file mode 100644 index 00000000..c1191278 --- /dev/null +++ b/actix_tls/connect/native_tls/reexports/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::native_tls::reexports - Rust
actix_tls::connect::native_tls

Module reexports

source
Expand description

Re-exports from native-tls and tokio-native-tls that are useful for connectors.

+

Structs§

  • A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.
  • A builder for client-side TLS connections.
\ No newline at end of file diff --git a/actix_tls/connect/native_tls/reexports/sidebar-items.js b/actix_tls/connect/native_tls/reexports/sidebar-items.js new file mode 100644 index 00000000..aa9182e1 --- /dev/null +++ b/actix_tls/connect/native_tls/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["AsyncTlsStream","TlsConnector"]}; \ No newline at end of file diff --git a/actix_tls/connect/native_tls/reexports/struct.AsyncTlsStream.html b/actix_tls/connect/native_tls/reexports/struct.AsyncTlsStream.html new file mode 100644 index 00000000..3988eef9 --- /dev/null +++ b/actix_tls/connect/native_tls/reexports/struct.AsyncTlsStream.html @@ -0,0 +1,54 @@ +AsyncTlsStream in actix_tls::connect::native_tls::reexports - Rust
actix_tls::connect::native_tls::reexports

Struct AsyncTlsStream

source
pub struct AsyncTlsStream<S>(/* private fields */);
Expand description

A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.

+

A TlsStream<S> represents a handshake that has been completed successfully +and both the server and the client are ready for receiving and sending +data. Bytes read from a TlsStream are decrypted from S and bytes written +to a TlsStream are encrypted when passing through to S.

+

Implementations§

source§

impl<S> TlsStream<S>

source

pub fn get_ref(&self) -> &TlsStream<AllowStd<S>>

Returns a shared reference to the inner stream.

+
source

pub fn get_mut(&mut self) -> &mut TlsStream<AllowStd<S>>

Returns a mutable reference to the inner stream.

+

Trait Implementations§

source§

impl<S> AsRawFd for TlsStream<S>
where + S: AsRawFd,

source§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
source§

impl<S> AsyncRead for TlsStream<S>
where + S: AsyncRead + AsyncWrite + Unpin,

source§

fn poll_read( + self: Pin<&mut TlsStream<S>>, + ctx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
source§

impl<S> AsyncWrite for TlsStream<S>
where + S: AsyncRead + AsyncWrite + Unpin,

source§

fn poll_write( + self: Pin<&mut TlsStream<S>>, + ctx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Attempt to write bytes from buf into the object. Read more
source§

fn poll_flush( + self: Pin<&mut TlsStream<S>>, + ctx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
source§

fn poll_shutdown( + self: Pin<&mut TlsStream<S>>, + ctx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
source§

impl<S> Debug for TlsStream<S>
where + S: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl<IO> From<TlsStream<IO>> for TlsStream<IO>

source§

fn from(from: TlsStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<S> Freeze for TlsStream<S>

§

impl<S> RefUnwindSafe for TlsStream<S>
where + S: RefUnwindSafe,

§

impl<S> Send for TlsStream<S>
where + S: Send,

§

impl<S> Sync for TlsStream<S>
where + S: Sync,

§

impl<S> Unpin for TlsStream<S>
where + S: Unpin,

§

impl<S> UnwindSafe for TlsStream<S>
where + S: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/native_tls/reexports/struct.TlsConnector.html b/actix_tls/connect/native_tls/reexports/struct.TlsConnector.html new file mode 100644 index 00000000..c9b574c6 --- /dev/null +++ b/actix_tls/connect/native_tls/reexports/struct.TlsConnector.html @@ -0,0 +1,49 @@ +TlsConnector in actix_tls::connect::native_tls::reexports - Rust
actix_tls::connect::native_tls::reexports

Struct TlsConnector

pub struct TlsConnector(/* private fields */);
Expand description

A builder for client-side TLS connections.

+

§Examples

+
use native_tls::TlsConnector;
+use std::io::{Read, Write};
+use std::net::TcpStream;
+
+let connector = TlsConnector::new().unwrap();
+
+let stream = TcpStream::connect("google.com:443").unwrap();
+let mut stream = connector.connect("google.com", stream).unwrap();
+
+stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
+let mut res = vec![];
+stream.read_to_end(&mut res).unwrap();
+println!("{}", String::from_utf8_lossy(&res));
+

Implementations§

§

impl TlsConnector

pub fn new() -> Result<TlsConnector, Error>

Returns a new connector with default settings.

+

pub fn builder() -> TlsConnectorBuilder

Returns a new builder for a TlsConnector.

+

pub fn connect<S>( + &self, + domain: &str, + stream: S, +) -> Result<TlsStream<S>, HandshakeError<S>>
where + S: Read + Write,

Initiates a TLS handshake.

+

The provided domain will be used for both SNI and certificate hostname +validation.

+

If the socket is nonblocking and a WouldBlock error is returned during +the handshake, a HandshakeError::WouldBlock error will be returned +which can be used to restart the handshake when the socket is ready +again.

+

The domain is ignored if both SNI and hostname verification are +disabled.

+

Trait Implementations§

§

impl Clone for TlsConnector

§

fn clone(&self) -> TlsConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for TlsConnector

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/native_tls/sidebar-items.js b/actix_tls/connect/native_tls/sidebar-items.js new file mode 100644 index 00000000..96ff4fde --- /dev/null +++ b/actix_tls/connect/native_tls/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["TlsConnector"]}; \ No newline at end of file diff --git a/actix_tls/connect/native_tls/struct.TlsConnector.html b/actix_tls/connect/native_tls/struct.TlsConnector.html new file mode 100644 index 00000000..cea9b949 --- /dev/null +++ b/actix_tls/connect/native_tls/struct.TlsConnector.html @@ -0,0 +1,49 @@ +TlsConnector in actix_tls::connect::native_tls - Rust
actix_tls::connect::native_tls

Struct TlsConnector

source
pub struct TlsConnector { /* private fields */ }
Expand description

Connector service and factory using native-tls.

+

Implementations§

source§

impl TlsConnector

source

pub fn new(connector: NativeTlsConnector) -> Self

Constructs new connector service from a native-tls connector.

+

This type is it’s own service factory, so it can be used in that setting, too.

+

Trait Implementations§

source§

impl Clone for TlsConnector

source§

fn clone(&self) -> TlsConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

The native-tls connector is both it’s ServiceFactory and Service impl type. +As the factory and service share the same type and state.

+
source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = Pin<Box<dyn Future<Output = Result<<TlsConnector as Service<Connection<R, IO>>>::Response, <TlsConnector as Service<Connection<R, IO>>>::Error>>>>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, stream: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R: Host, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnector

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/index.html b/actix_tls/connect/openssl/index.html new file mode 100644 index 00000000..3ac71ea7 --- /dev/null +++ b/actix_tls/connect/openssl/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::openssl - Rust
actix_tls::connect

Module openssl

source
Expand description

OpenSSL based connector service.

+

See TlsConnector for main connector service factory docs.

+

Modules§

  • Re-exports from openssl and tokio-openssl that are useful for connectors.

Structs§

\ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/enum.HandshakeError.html b/actix_tls/connect/openssl/reexports/enum.HandshakeError.html new file mode 100644 index 00000000..805ecb5c --- /dev/null +++ b/actix_tls/connect/openssl/reexports/enum.HandshakeError.html @@ -0,0 +1,32 @@ +HandshakeError in actix_tls::connect::openssl::reexports - Rust
actix_tls::connect::openssl::reexports

Enum HandshakeError

source
pub enum HandshakeError<S> {
+    SetupFailure(ErrorStack),
+    Failure(MidHandshakeSslStream<S>),
+    WouldBlock(MidHandshakeSslStream<S>),
+}
Expand description

An error or intermediate state after a TLS handshake attempt.

+

Variants§

§

SetupFailure(ErrorStack)

Setup failed.

+
§

Failure(MidHandshakeSslStream<S>)

The handshake failed.

+
§

WouldBlock(MidHandshakeSslStream<S>)

The handshake encountered a WouldBlock error midway through.

+

This error will never be returned for blocking streams.

+

Trait Implementations§

source§

impl<S> Debug for HandshakeError<S>
where + S: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl<S> Display for HandshakeError<S>
where + S: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl<S> Error for HandshakeError<S>
where + S: Debug,

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
source§

impl<S> From<ErrorStack> for HandshakeError<S>

source§

fn from(e: ErrorStack) -> HandshakeError<S>

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<S> Freeze for HandshakeError<S>

§

impl<S> !RefUnwindSafe for HandshakeError<S>

§

impl<S> Send for HandshakeError<S>
where + S: Send,

§

impl<S> Sync for HandshakeError<S>
where + S: Sync,

§

impl<S> Unpin for HandshakeError<S>
where + S: Unpin,

§

impl<S> !UnwindSafe for HandshakeError<S>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/index.html b/actix_tls/connect/openssl/reexports/index.html new file mode 100644 index 00000000..7d44c4e7 --- /dev/null +++ b/actix_tls/connect/openssl/reexports/index.html @@ -0,0 +1,2 @@ +actix_tls::connect::openssl::reexports - Rust
actix_tls::connect::openssl

Module reexports

source
Expand description

Re-exports from openssl and tokio-openssl that are useful for connectors.

+

Structs§

Enums§

  • An error or intermediate state after a TLS handshake attempt.
\ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/sidebar-items.js b/actix_tls/connect/openssl/reexports/sidebar-items.js new file mode 100644 index 00000000..611d6350 --- /dev/null +++ b/actix_tls/connect/openssl/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["HandshakeError"],"struct":["AsyncSslStream","Error","SslConnector","SslConnectorBuilder","SslMethod"]}; \ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/struct.AsyncSslStream.html b/actix_tls/connect/openssl/reexports/struct.AsyncSslStream.html new file mode 100644 index 00000000..abe1fa66 --- /dev/null +++ b/actix_tls/connect/openssl/reexports/struct.AsyncSslStream.html @@ -0,0 +1,94 @@ +AsyncSslStream in actix_tls::connect::openssl::reexports - Rust
actix_tls::connect::openssl::reexports

Struct AsyncSslStream

pub struct AsyncSslStream<S>(/* private fields */);
Expand description

An asynchronous version of openssl::ssl::SslStream.

+

Implementations§

§

impl<S> SslStream<S>
where + S: AsyncRead + AsyncWrite,

pub fn new(ssl: Ssl, stream: S) -> Result<SslStream<S>, ErrorStack>

pub fn poll_connect( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

pub async fn connect(self: Pin<&mut SslStream<S>>) -> Result<(), Error>

A convenience method wrapping poll_connect.

+

pub fn poll_accept( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

pub async fn accept(self: Pin<&mut SslStream<S>>) -> Result<(), Error>

A convenience method wrapping poll_accept.

+

pub fn poll_do_handshake( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

pub async fn do_handshake(self: Pin<&mut SslStream<S>>) -> Result<(), Error>

A convenience method wrapping poll_do_handshake.

+

pub fn poll_peek( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, + buf: &mut [u8], +) -> Poll<Result<usize, Error>>

pub async fn peek( + self: Pin<&mut SslStream<S>>, + buf: &mut [u8], +) -> Result<usize, Error>

A convenience method wrapping poll_peek.

+

pub fn poll_read_early_data( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, + buf: &mut [u8], +) -> Poll<Result<usize, Error>>

pub async fn read_early_data( + self: Pin<&mut SslStream<S>>, + buf: &mut [u8], +) -> Result<usize, Error>

A convenience method wrapping poll_read_early_data.

+

pub fn poll_write_early_data( + self: Pin<&mut SslStream<S>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

pub async fn write_early_data( + self: Pin<&mut SslStream<S>>, + buf: &[u8], +) -> Result<usize, Error>

A convenience method wrapping poll_write_early_data.

+
§

impl<S> SslStream<S>

pub fn ssl(&self) -> &SslRef

Returns a shared reference to the Ssl object associated with this stream.

+

pub fn get_ref(&self) -> &S

Returns a shared reference to the underlying stream.

+

pub fn get_mut(&mut self) -> &mut S

Returns a mutable reference to the underlying stream.

+

pub fn get_pin_mut(self: Pin<&mut SslStream<S>>) -> Pin<&mut S>

Returns a pinned mutable reference to the underlying stream.

+

Trait Implementations§

§

impl<S> AsyncRead for SslStream<S>
where + S: AsyncRead + AsyncWrite,

§

fn poll_read( + self: Pin<&mut SslStream<S>>, + ctx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
§

impl<S> AsyncWrite for SslStream<S>
where + S: AsyncRead + AsyncWrite,

§

fn poll_write( + self: Pin<&mut SslStream<S>>, + ctx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Attempt to write bytes from buf into the object. Read more
§

fn poll_flush( + self: Pin<&mut SslStream<S>>, + ctx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
§

fn poll_shutdown( + self: Pin<&mut SslStream<S>>, + ctx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
§

impl<S> Debug for SslStream<S>
where + S: Debug,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl<IO> From<SslStream<IO>> for TlsStream<IO>

source§

fn from(from: SslStream<IO>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<S> Freeze for SslStream<S>

§

impl<S> RefUnwindSafe for SslStream<S>
where + S: RefUnwindSafe,

§

impl<S> Send for SslStream<S>
where + S: Send,

§

impl<S> Sync for SslStream<S>
where + S: Sync,

§

impl<S> Unpin for SslStream<S>
where + S: Unpin,

§

impl<S> UnwindSafe for SslStream<S>
where + S: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/struct.Error.html b/actix_tls/connect/openssl/reexports/struct.Error.html new file mode 100644 index 00000000..6b1e2b0b --- /dev/null +++ b/actix_tls/connect/openssl/reexports/struct.Error.html @@ -0,0 +1,18 @@ +Error in actix_tls::connect::openssl::reexports - Rust
actix_tls::connect::openssl::reexports

Struct Error

source
pub struct Error { /* private fields */ }
Expand description

An SSL error.

+

Implementations§

source§

impl Error

source

pub fn code(&self) -> ErrorCode

source

pub fn io_error(&self) -> Option<&Error>

source

pub fn into_io_error(self) -> Result<Error, Error>

source

pub fn ssl_error(&self) -> Option<&ErrorStack>

Trait Implementations§

source§

impl Debug for Error

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Display for Error

source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl Error for Error

source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
source§

impl From<ErrorStack> for Error

source§

fn from(e: ErrorStack) -> Error

Converts to this type from the input type.

Auto Trait Implementations§

§

impl Freeze for Error

§

impl !RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl !UnwindSafe for Error

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/struct.SslConnector.html b/actix_tls/connect/openssl/reexports/struct.SslConnector.html new file mode 100644 index 00000000..8b803ccd --- /dev/null +++ b/actix_tls/connect/openssl/reexports/struct.SslConnector.html @@ -0,0 +1,35 @@ +SslConnector in actix_tls::connect::openssl::reexports - Rust
actix_tls::connect::openssl::reexports

Struct SslConnector

source
pub struct SslConnector(/* private fields */);
Expand description

A type which wraps client-side streams in a TLS session.

+

OpenSSL’s default configuration is highly insecure. This connector manages the OpenSSL +structures, configuring cipher suites, session options, hostname verification, and more.

+

OpenSSL’s built-in hostname verification is used when linking against OpenSSL 1.0.2 or 1.1.0, +and a custom implementation is used when linking against OpenSSL 1.0.1.

+

Implementations§

source§

impl SslConnector

source

pub fn builder(method: SslMethod) -> Result<SslConnectorBuilder, ErrorStack>

Creates a new builder for TLS connections.

+

The default configuration is subject to change, and is currently derived from Python.

+
source

pub fn connect<S>( + &self, + domain: &str, + stream: S, +) -> Result<SslStream<S>, HandshakeError<S>>
where + S: Read + Write,

Initiates a client-side TLS session on a stream.

+

The domain is used for SNI and hostname verification.

+
source

pub fn configure(&self) -> Result<ConnectConfiguration, ErrorStack>

Returns a structure allowing for configuration of a single TLS session before connection.

+
source

pub fn into_context(self) -> SslContext

Consumes the SslConnector, returning the inner raw SslContext.

+
source

pub fn context(&self) -> &SslContextRef

Returns a shared reference to the inner raw SslContext.

+

Trait Implementations§

source§

impl Clone for SslConnector

source§

fn clone(&self) -> SslConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for SslConnector

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/struct.SslConnectorBuilder.html b/actix_tls/connect/openssl/reexports/struct.SslConnectorBuilder.html new file mode 100644 index 00000000..33f3ddbd --- /dev/null +++ b/actix_tls/connect/openssl/reexports/struct.SslConnectorBuilder.html @@ -0,0 +1,326 @@ +SslConnectorBuilder in actix_tls::connect::openssl::reexports - Rust
actix_tls::connect::openssl::reexports

Struct SslConnectorBuilder

source
pub struct SslConnectorBuilder(/* private fields */);
Expand description

A builder for SslConnectors.

+

Implementations§

source§

impl SslConnectorBuilder

source

pub fn build(self) -> SslConnector

Consumes the builder, returning an SslConnector.

+

Methods from Deref<Target = SslContextBuilder>§

source

pub fn as_ptr(&self) -> *mut SSL_CTX

Returns a pointer to the raw OpenSSL value.

+
source

pub fn set_verify(&mut self, mode: SslVerifyMode)

Configures the certificate verification method for new connections.

+

This corresponds to SSL_CTX_set_verify.

+
source

pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
where + F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,

Configures the certificate verification method for new connections and +registers a verification callback.

+

The callback is passed a boolean indicating if OpenSSL’s internal verification succeeded as +well as a reference to the X509StoreContext which can be used to examine the certificate +chain. It should return a boolean indicating if verification succeeded.

+

This corresponds to SSL_CTX_set_verify.

+
source

pub fn set_servername_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,

Configures the server name indication (SNI) callback for new connections.

+

SNI is used to allow a single server to handle requests for multiple domains, each of which +has its own certificate chain and configuration.

+

Obtain the server name with the servername method and then set the corresponding context +with set_ssl_context

+

This corresponds to SSL_CTX_set_tlsext_servername_callback.

+
source

pub fn set_verify_depth(&mut self, depth: u32)

Sets the certificate verification depth.

+

If the peer’s certificate chain is longer than this value, verification will fail.

+

This corresponds to SSL_CTX_set_verify_depth.

+
source

pub fn set_verify_cert_store( + &mut self, + cert_store: X509Store, +) -> Result<(), ErrorStack>

Sets a custom certificate store for verifying peer certificates.

+

Requires OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_set0_verify_cert_store.

+
source

pub fn set_cert_store(&mut self, cert_store: X509Store)

Replaces the context’s certificate store.

+

This corresponds to SSL_CTX_set_cert_store.

+
source

pub fn set_read_ahead(&mut self, read_ahead: bool)

Controls read ahead behavior.

+

If enabled, OpenSSL will read as much data as is available from the underlying stream, +instead of a single record at a time.

+

It has no effect when used with DTLS.

+

This corresponds to SSL_CTX_set_read_ahead.

+
source

pub fn set_mode(&mut self, mode: SslMode) -> SslMode

Sets the mode used by the context, returning the previous mode.

+

This corresponds to SSL_CTX_set_mode.

+
source

pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack>

Sets the parameters to be used during ephemeral Diffie-Hellman key exchange.

+

This corresponds to SSL_CTX_set_tmp_dh.

+
source

pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,

Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman +key exchange.

+

The callback is provided with a reference to the Ssl for the session, as well as a boolean +indicating if the selected cipher is export-grade, and the key length. The export and key +length options are archaic and should be ignored in almost all cases.

+

This corresponds to SSL_CTX_set_tmp_dh_callback.

+
source

pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack>

Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange.

+

This corresponds to SSL_CTX_set_tmp_ecdh.

+
source

pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack>

Use the default locations of trusted certificates for verification.

+

These locations are read from the SSL_CERT_FILE and SSL_CERT_DIR environment variables +if present, or defaults specified at OpenSSL build time otherwise.

+

This corresponds to SSL_CTX_set_default_verify_paths.

+
source

pub fn set_ca_file<P>(&mut self, file: P) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads trusted root certificates from a file.

+

The file should contain a sequence of PEM-formatted CA certificates.

+

This corresponds to SSL_CTX_load_verify_locations.

+
source

pub fn set_client_ca_list(&mut self, list: Stack<X509Name>)

Sets the list of CA names sent to the client.

+

The CA certificates must still be added to the trust root - they are not automatically set +as trusted by this method.

+

This corresponds to SSL_CTX_set_client_CA_list.

+
source

pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack>

Add the provided CA certificate to the list sent by the server to the client when +requesting client-side TLS authentication.

+

This corresponds to SSL_CTX_add_client_CA.

+
source

pub fn set_session_id_context( + &mut self, + sid_ctx: &[u8], +) -> Result<(), ErrorStack>

Set the context identifier for sessions.

+

This value identifies the server’s session cache to clients, telling them when they’re +able to reuse sessions. It should be set to a unique value per server, unless multiple +servers share a session cache.

+

This value should be set when using client certificates, or each request will fail its +handshake and need to be restarted.

+

This corresponds to SSL_CTX_set_session_id_context.

+
source

pub fn set_certificate_file<P>( + &mut self, + file: P, + file_type: SslFiletype, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads a leaf certificate from a file.

+

Only a single certificate will be loaded - use add_extra_chain_cert to add the remainder +of the certificate chain, or set_certificate_chain_file to load the entire chain from a +single file.

+

This corresponds to SSL_CTX_use_certificate_file.

+
source

pub fn set_certificate_chain_file<P>( + &mut self, + file: P, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads a certificate chain from a file.

+

The file should contain a sequence of PEM-formatted certificates, the first being the leaf +certificate, and the remainder forming the chain of certificates up to and including the +trusted root certificate.

+

This corresponds to SSL_CTX_use_certificate_chain_file.

+
source

pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack>

Sets the leaf certificate.

+

Use add_extra_chain_cert to add the remainder of the certificate chain.

+

This corresponds to SSL_CTX_use_certificate.

+
source

pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack>

Appends a certificate to the certificate chain.

+

This chain should contain all certificates necessary to go from the certificate specified by +set_certificate to a trusted root.

+

This corresponds to SSL_CTX_add_extra_chain_cert.

+
source

pub fn set_private_key_file<P>( + &mut self, + file: P, + file_type: SslFiletype, +) -> Result<(), ErrorStack>
where + P: AsRef<Path>,

Loads the private key from a file.

+

This corresponds to SSL_CTX_use_PrivateKey_file.

+
source

pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
where + T: HasPrivate,

Sets the private key.

+

This corresponds to SSL_CTX_use_PrivateKey.

+
source

pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack>

Sets the list of supported ciphers for protocols before TLSv1.3.

+

The set_ciphersuites method controls the cipher suites for TLSv1.3.

+

See ciphers for details on the format.

+

This corresponds to SSL_CTX_set_cipher_list.

+
source

pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack>

Sets the list of supported ciphers for the TLSv1.3 protocol.

+

The set_cipher_list method controls the cipher suites for protocols before TLSv1.3.

+

The format consists of TLSv1.3 cipher suite names separated by : characters in order of +preference.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+

This corresponds to SSL_CTX_set_ciphersuites.

+
source

pub fn set_options(&mut self, option: SslOptions) -> SslOptions

Sets the options used by the context, returning the old set.

+
§Note
+

This enables the specified options, but does not disable unspecified options. Use +clear_options for that.

+

This corresponds to SSL_CTX_set_options.

+
source

pub fn options(&self) -> SslOptions

Returns the options used by the context.

+

This corresponds to SSL_CTX_get_options.

+
source

pub fn clear_options(&mut self, option: SslOptions) -> SslOptions

Clears the options used by the context, returning the old set.

+

This corresponds to SSL_CTX_clear_options.

+
source

pub fn set_min_proto_version( + &mut self, + version: Option<SslVersion>, +) -> Result<(), ErrorStack>

Sets the minimum supported protocol version.

+

A value of None will enable protocol versions down to the lowest version supported by +OpenSSL.

+

Requires BoringSSL or OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_min_proto_version.

+
source

pub fn set_max_proto_version( + &mut self, + version: Option<SslVersion>, +) -> Result<(), ErrorStack>

Sets the maximum supported protocol version.

+

A value of None will enable protocol versions up to the highest version supported by +OpenSSL.

+

Requires BoringSSL or OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_max_proto_version.

+
source

pub fn min_proto_version(&mut self) -> Option<SslVersion>

Gets the minimum supported protocol version.

+

A value of None indicates that all versions down to the lowest version supported by +OpenSSL are enabled.

+

Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.

+

This corresponds to SSL_CTX_get_min_proto_version.

+
source

pub fn max_proto_version(&mut self) -> Option<SslVersion>

Gets the maximum supported protocol version.

+

A value of None indicates that all versions up to the highest version supported by +OpenSSL are enabled.

+

Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.

+

This corresponds to SSL_CTX_get_max_proto_version.

+
source

pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack>

Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN).

+

The input must be in ALPN “wire format”. It consists of a sequence of supported protocol +names prefixed by their byte length. For example, the protocol list consisting of spdy/1 +and http/1.1 is encoded as b"\x06spdy/1\x08http/1.1". The protocols are ordered by +preference.

+

Requires BoringSSL or OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_alpn_protos.

+
source

pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack>

Enables the DTLS extension “use_srtp” as defined in RFC5764.

+

This corresponds to SSL_CTX_set_tlsext_use_srtp.

+
source

pub fn set_alpn_select_callback<F>(&mut self, callback: F)
where + F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,

Sets the callback used by a server to select a protocol for Application Layer Protocol +Negotiation (ALPN).

+

The callback is provided with the client’s protocol list in ALPN wire format. See the +documentation for SslContextBuilder::set_alpn_protos for details. It should return one +of those protocols on success. The select_next_proto function implements the standard +protocol selection algorithm.

+

Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.

+

This corresponds to SSL_CTX_set_alpn_select_cb.

+
source

pub fn check_private_key(&self) -> Result<(), ErrorStack>

Checks for consistency between the private key and certificate.

+

This corresponds to SSL_CTX_check_private_key.

+
source

pub fn cert_store(&self) -> &X509StoreBuilderRef

Returns a shared reference to the context’s certificate store.

+

This corresponds to SSL_CTX_get_cert_store.

+
source

pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef

Returns a mutable reference to the context’s certificate store.

+

This corresponds to SSL_CTX_get_cert_store.

+
source

pub fn verify_param(&self) -> &X509VerifyParamRef

Returns a reference to the X509 verification configuration.

+

Requires BoringSSL or OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_get0_param.

+
source

pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef

Returns a mutable reference to the X509 verification configuration.

+

Requires BoringSSL or OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_get0_param.

+
source

pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
where + F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,

Sets the callback dealing with OCSP stapling.

+

On the client side, this callback is responsible for validating the OCSP status response +returned by the server. The status may be retrieved with the SslRef::ocsp_status method. +A response of Ok(true) indicates that the OCSP status is valid, and a response of +Ok(false) indicates that the OCSP status is invalid and the handshake should be +terminated.

+

On the server side, this callback is responsible for setting the OCSP status response to be +returned to clients. The status may be set with the SslRef::set_ocsp_status method. A +response of Ok(true) indicates that the OCSP status should be returned to the client, and +Ok(false) indicates that the status should not be returned to the client.

+

This corresponds to SSL_CTX_set_tlsext_status_cb.

+
source

pub fn set_psk_client_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,

Sets the callback for providing an identity and pre-shared key for a TLS-PSK client.

+

The callback will be called with the SSL context, an identity hint if one was provided +by the server, a mutable slice for each of the identity and pre-shared key bytes. The +identity must be written as a null-terminated C string.

+

This corresponds to SSL_CTX_set_psk_client_callback.

+
source

pub fn set_psk_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,

👎Deprecated since 0.10.10: renamed to set_psk_client_callback
source

pub fn set_psk_server_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,

Sets the callback for providing an identity and pre-shared key for a TLS-PSK server.

+

The callback will be called with the SSL context, an identity provided by the client, +and, a mutable slice for the pre-shared key bytes. The callback returns the number of +bytes in the pre-shared key.

+

This corresponds to SSL_CTX_set_psk_server_callback.

+
source

pub fn set_new_session_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,

Sets the callback which is called when new sessions are negotiated.

+

This can be used by clients to implement session caching. While in TLSv1.2 the session is +available to access via SslRef::session immediately after the handshake completes, this +is not the case for TLSv1.3. There, a session is not generally available immediately, and +the server may provide multiple session tokens to the client over a single session. The new +session callback is a portable way to deal with both cases.

+

Note that session caching must be enabled for the callback to be invoked, and it defaults +off for clients. set_session_cache_mode controls that behavior.

+

This corresponds to SSL_CTX_sess_set_new_cb.

+
source

pub fn set_remove_session_callback<F>(&mut self, callback: F)
where + F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,

Sets the callback which is called when sessions are removed from the context.

+

Sessions can be removed because they have timed out or because they are considered faulty.

+

This corresponds to SSL_CTX_sess_set_remove_cb.

+
source

pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,

Sets the callback which is called when a client proposed to resume a session but it was not +found in the internal cache.

+

The callback is passed a reference to the session ID provided by the client. It should +return the session corresponding to that ID if available. This is only used for servers, not +clients.

+
§Safety
+

The returned SslSession must not be associated with a different SslContext.

+

This corresponds to SSL_CTX_sess_set_get_cb.

+
source

pub fn set_keylog_callback<F>(&mut self, callback: F)
where + F: Fn(&SslRef, &str) + 'static + Sync + Send,

Sets the TLS key logging callback.

+

The callback is invoked whenever TLS key material is generated, and is passed a line of NSS +SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message +traffic. The line does not contain a trailing newline.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_set_keylog_callback.

+
source

pub fn set_session_cache_mode( + &mut self, + mode: SslSessionCacheMode, +) -> SslSessionCacheMode

Sets the session caching mode use for connections made with the context.

+

Returns the previous session caching mode.

+

This corresponds to SSL_CTX_set_session_cache_mode.

+

Sets the callback for generating an application cookie for TLS1.3 +stateless handshakes.

+

The callback will be called with the SSL context and a slice into which the cookie +should be written. The callback should return the number of bytes written.

+

This corresponds to SSL_CTX_set_stateless_cookie_generate_cb.

+

Sets the callback for verifying an application cookie for TLS1.3 +stateless handshakes.

+

The callback will be called with the SSL context and the cookie supplied by the +client. It should return true if and only if the cookie is valid.

+

Note that the OpenSSL implementation independently verifies the integrity of +application cookies using an HMAC before invoking the supplied callback.

+

This corresponds to SSL_CTX_set_stateless_cookie_verify_cb.

+

Sets the callback for generating a DTLSv1 cookie

+

The callback will be called with the SSL context and a slice into which the cookie +should be written. The callback should return the number of bytes written.

+

This corresponds to SSL_CTX_set_cookie_generate_cb.

+

Sets the callback for verifying a DTLSv1 cookie

+

The callback will be called with the SSL context and the cookie supplied by the +client. It should return true if and only if the cookie is valid.

+

This corresponds to SSL_CTX_set_cookie_verify_cb.

+
source

pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T)

Sets the extra data at the specified index.

+

This can be used to provide data to callbacks registered with the context. Use the +SslContext::new_ex_index method to create an Index.

+

This corresponds to SSL_CTX_set_ex_data.

+
source

pub fn add_custom_ext<AddFn, ParseFn, T>( + &mut self, + ext_type: u16, + context: ExtensionContext, + add_cb: AddFn, + parse_cb: ParseFn, +) -> Result<(), ErrorStack>
where + AddFn: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert> + 'static + Sync + Send, + T: AsRef<[u8]> + 'static + Sync + Send, + ParseFn: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert> + 'static + Sync + Send,

Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_add_custom_ext.

+
source

pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack>

Sets the maximum amount of early data that will be accepted on incoming connections.

+

Defaults to 0.

+

Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.

+

This corresponds to SSL_CTX_set_max_early_data.

+
source

pub fn set_client_hello_callback<F>(&mut self, callback: F)
where + F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack> + 'static + Sync + Send,

Sets a callback which will be invoked just after the client’s hello message is received.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_set_client_hello_cb.

+
source

pub fn set_session_cache_size(&mut self, size: i32) -> i64

Sets the context’s session cache size limit, returning the previous limit.

+

A value of 0 means that the cache size is unbounded.

+

This corresponds to SSL_CTX_sess_set_cache_size.

+
source

pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack>

Sets the context’s supported signature algorithms.

+

Requires OpenSSL 1.0.2 or newer.

+

This corresponds to SSL_CTX_set1_sigalgs_list.

+
source

pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack>

Sets the context’s supported elliptic curve groups.

+

Requires BoringSSL or OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer.

+

This corresponds to SSL_CTX_set1_groups_list.

+
source

pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack>

Sets the number of TLS 1.3 session tickets that will be sent to a client after a full +handshake.

+

Requires OpenSSL 1.1.1 or newer.

+

This corresponds to SSL_CTX_set_num_tickets.

+
source

pub fn set_security_level(&mut self, level: u32)

Set the context’s security level to a value between 0 and 5, inclusive. +A security value of 0 allows allows all parameters and algorithms.

+

Requires OpenSSL 1.1.0 or newer.

+

This corresponds to SSL_CTX_set_security_level.

+

Trait Implementations§

source§

impl Deref for SslConnectorBuilder

source§

type Target = SslContextBuilder

The resulting type after dereferencing.
source§

fn deref(&self) -> &SslContextBuilder

Dereferences the value.
source§

impl DerefMut for SslConnectorBuilder

source§

fn deref_mut(&mut self) -> &mut SslContextBuilder

Mutably dereferences the value.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/reexports/struct.SslMethod.html b/actix_tls/connect/openssl/reexports/struct.SslMethod.html new file mode 100644 index 00000000..642cfb88 --- /dev/null +++ b/actix_tls/connect/openssl/reexports/struct.SslMethod.html @@ -0,0 +1,31 @@ +SslMethod in actix_tls::connect::openssl::reexports - Rust
actix_tls::connect::openssl::reexports

Struct SslMethod

source
pub struct SslMethod(/* private fields */);
Expand description

A type specifying the kind of protocol an SslContext will speak.

+

Implementations§

source§

impl SslMethod

source

pub fn tls() -> SslMethod

Support all versions of the TLS protocol.

+

This corresponds to TLS_method.

+
source

pub fn dtls() -> SslMethod

Support all versions of the DTLS protocol.

+

This corresponds to DTLS_method.

+
source

pub fn tls_client() -> SslMethod

Support all versions of the TLS protocol, explicitly as a client.

+

This corresponds to TLS_client_method.

+
source

pub fn tls_server() -> SslMethod

Support all versions of the TLS protocol, explicitly as a server.

+

This corresponds to TLS_server_method.

+
source

pub unsafe fn from_ptr(ptr: *const SSL_METHOD) -> SslMethod

Constructs an SslMethod from a pointer to the underlying OpenSSL value.

+
§Safety
+

The caller must ensure the pointer is valid.

+
source

pub fn as_ptr(&self) -> *const SSL_METHOD

Returns a pointer to the underlying OpenSSL value.

+

Trait Implementations§

source§

impl Clone for SslMethod

source§

fn clone(&self) -> SslMethod

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Copy for SslMethod

source§

impl Send for SslMethod

source§

impl Sync for SslMethod

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/sidebar-items.js b/actix_tls/connect/openssl/sidebar-items.js new file mode 100644 index 00000000..27e2fa41 --- /dev/null +++ b/actix_tls/connect/openssl/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["reexports"],"struct":["TlsConnector","TlsConnectorService"]}; \ No newline at end of file diff --git a/actix_tls/connect/openssl/struct.TlsConnector.html b/actix_tls/connect/openssl/struct.TlsConnector.html new file mode 100644 index 00000000..171eb9fb --- /dev/null +++ b/actix_tls/connect/openssl/struct.TlsConnector.html @@ -0,0 +1,36 @@ +TlsConnector in actix_tls::connect::openssl - Rust
actix_tls::connect::openssl

Struct TlsConnector

source
pub struct TlsConnector { /* private fields */ }
Expand description

Connector service factory using openssl.

+

Implementations§

source§

impl TlsConnector

source

pub fn new(connector: SslConnector) -> Self

Constructs new connector service factory from an openssl connector.

+
source

pub fn service(connector: SslConnector) -> TlsConnectorService

Constructs new connector service from an openssl connector.

+

Trait Implementations§

source§

impl Clone for TlsConnector

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, SslStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/openssl/struct.TlsConnectorService.html b/actix_tls/connect/openssl/struct.TlsConnectorService.html new file mode 100644 index 00000000..5d386e2d --- /dev/null +++ b/actix_tls/connect/openssl/struct.TlsConnectorService.html @@ -0,0 +1,31 @@ +TlsConnectorService in actix_tls::connect::openssl - Rust
actix_tls::connect::openssl

Struct TlsConnectorService

source
pub struct TlsConnectorService { /* private fields */ }
Expand description

Connector service using openssl.

+

Trait Implementations§

source§

impl Clone for TlsConnectorService

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, SslStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, stream: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/resolve/trait.Resolve.html b/actix_tls/connect/resolve/trait.Resolve.html new file mode 100644 index 00000000..960a66f0 --- /dev/null +++ b/actix_tls/connect/resolve/trait.Resolve.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/trait.Resolve.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/resolver/struct.Resolver.html b/actix_tls/connect/resolver/struct.Resolver.html new file mode 100644 index 00000000..e3562aef --- /dev/null +++ b/actix_tls/connect/resolver/struct.Resolver.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/struct.Resolver.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/resolver/struct.ResolverService.html b/actix_tls/connect/resolver/struct.ResolverService.html new file mode 100644 index 00000000..8cfb92b9 --- /dev/null +++ b/actix_tls/connect/resolver/struct.ResolverService.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_tls/connect/struct.ResolverService.html...

+ + + \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/fn.native_roots_cert_store.html b/actix_tls/connect/rustls_0_20/fn.native_roots_cert_store.html new file mode 100644 index 00000000..9a12bd6f --- /dev/null +++ b/actix_tls/connect/rustls_0_20/fn.native_roots_cert_store.html @@ -0,0 +1,3 @@ +native_roots_cert_store in actix_tls::connect::rustls_0_20 - Rust
actix_tls::connect::rustls_0_20

Function native_roots_cert_store

source
pub fn native_roots_cert_store() -> Result<RootCertStore>
Expand description

Returns root certificates via rustls-native-certs crate as a rustls certificate store.

+

See rustls_native_certs::load_native_certs() for more info on behavior and errors.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/fn.webpki_roots_cert_store.html b/actix_tls/connect/rustls_0_20/fn.webpki_roots_cert_store.html new file mode 100644 index 00000000..62189d9e --- /dev/null +++ b/actix_tls/connect/rustls_0_20/fn.webpki_roots_cert_store.html @@ -0,0 +1,2 @@ +webpki_roots_cert_store in actix_tls::connect::rustls_0_20 - Rust
actix_tls::connect::rustls_0_20

Function webpki_roots_cert_store

source
pub fn webpki_roots_cert_store() -> RootCertStore
Expand description

Returns standard root certificates from webpki-roots crate as a rustls certificate store.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/index.html b/actix_tls/connect/rustls_0_20/index.html new file mode 100644 index 00000000..f413ebc9 --- /dev/null +++ b/actix_tls/connect/rustls_0_20/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::rustls_0_20 - Rust
actix_tls::connect

Module rustls_0_20

source
Expand description

Rustls based connector service.

+

See TlsConnector for main connector service factory docs.

+

Modules§

  • Re-exports from the rustls v0.20 ecosystem that are useful for connectors.

Structs§

Functions§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/reexports/index.html b/actix_tls/connect/rustls_0_20/reexports/index.html new file mode 100644 index 00000000..5cd88432 --- /dev/null +++ b/actix_tls/connect/rustls_0_20/reexports/index.html @@ -0,0 +1,4 @@ +actix_tls::connect::rustls_0_20::reexports - Rust
actix_tls::connect::rustls_0_20

Module reexports

source
Expand description

Re-exports from the rustls v0.20 ecosystem that are useful for connectors.

+

Structs§

  • A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.
  • Common configuration for (typically) all connections made by +a program.

Statics§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/reexports/sidebar-items.js b/actix_tls/connect/rustls_0_20/reexports/sidebar-items.js new file mode 100644 index 00000000..5f006fad --- /dev/null +++ b/actix_tls/connect/rustls_0_20/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"static":["TLS_SERVER_ROOTS"],"struct":["AsyncTlsStream","ClientConfig"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/reexports/static.TLS_SERVER_ROOTS.html b/actix_tls/connect/rustls_0_20/reexports/static.TLS_SERVER_ROOTS.html new file mode 100644 index 00000000..2234e58d --- /dev/null +++ b/actix_tls/connect/rustls_0_20/reexports/static.TLS_SERVER_ROOTS.html @@ -0,0 +1 @@ +TLS_SERVER_ROOTS in actix_tls::connect::rustls_0_20::reexports - Rust
actix_tls::connect::rustls_0_20::reexports

Static TLS_SERVER_ROOTS

pub static TLS_SERVER_ROOTS: TlsServerTrustAnchors<'static>
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/reexports/struct.AsyncTlsStream.html b/actix_tls/connect/rustls_0_20/reexports/struct.AsyncTlsStream.html new file mode 100644 index 00000000..af5c1744 --- /dev/null +++ b/actix_tls/connect/rustls_0_20/reexports/struct.AsyncTlsStream.html @@ -0,0 +1,49 @@ +AsyncTlsStream in actix_tls::connect::rustls_0_20::reexports - Rust
actix_tls::connect::rustls_0_20::reexports

Struct AsyncTlsStream

pub struct AsyncTlsStream<IO> { /* private fields */ }
Expand description

A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.

+

Implementations§

§

impl<IO> TlsStream<IO>

pub fn get_ref(&self) -> (&IO, &ClientConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ClientConnection)

pub fn into_inner(self) -> (IO, ClientConnection)

Trait Implementations§

§

impl<S> AsRawFd for TlsStream<S>
where + S: AsRawFd,

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl<IO> AsyncRead for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_read( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
§

impl<IO> AsyncWrite for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_write( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Note: that it does not guarantee the final data to be sent. +To be cautious, you must manually call flush.

+
§

fn poll_flush( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
§

fn poll_shutdown( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
§

impl<IO> Debug for TlsStream<IO>
where + IO: Debug,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/reexports/struct.ClientConfig.html b/actix_tls/connect/rustls_0_20/reexports/struct.ClientConfig.html new file mode 100644 index 00000000..d146c27b --- /dev/null +++ b/actix_tls/connect/rustls_0_20/reexports/struct.ClientConfig.html @@ -0,0 +1,63 @@ +ClientConfig in actix_tls::connect::rustls_0_20::reexports - Rust
actix_tls::connect::rustls_0_20::reexports

Struct ClientConfig

pub struct ClientConfig {
+    pub alpn_protocols: Vec<Vec<u8>>,
+    pub session_storage: Arc<dyn StoresClientSessions>,
+    pub max_fragment_size: Option<usize>,
+    pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
+    pub enable_tickets: bool,
+    pub enable_sni: bool,
+    pub key_log: Arc<dyn KeyLog>,
+    pub enable_early_data: bool,
+    /* private fields */
+}
Expand description

Common configuration for (typically) all connections made by +a program.

+

Making one of these can be expensive, and should be +once per process rather than once per connection.

+

These must be created via the ClientConfig::builder() function.

+

§Defaults

+ +

Fields§

§alpn_protocols: Vec<Vec<u8>>

Which ALPN protocols we include in our client hello. +If empty, no ALPN extension is sent.

+
§session_storage: Arc<dyn StoresClientSessions>

How we store session data or tickets.

+
§max_fragment_size: Option<usize>

The maximum size of TLS message we’ll emit. If None, we don’t limit TLS +message lengths except to the 2**16 limit specified in the standard.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ClientConnection::new.

+

Setting this value to the TCP MSS may improve latency for stream-y workloads.

+
§client_auth_cert_resolver: Arc<dyn ResolvesClientCert>

How to decide what client auth certificate/keys to use.

+
§enable_tickets: bool

Whether to support RFC5077 tickets. You must provide a working +session_storage member for this to have any meaningful +effect.

+

The default is true.

+
§enable_sni: bool

Whether to send the Server Name Indication (SNI) extension +during the client handshake.

+

The default is true.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§enable_early_data: bool

Whether to send data on the first flight (“early data”) in +TLS 1.3 handshakes.

+

The default is false.

+

Implementations§

§

impl ClientConfig

pub fn builder() -> ConfigBuilder<ClientConfig, WantsCipherSuites>

Create a builder to build up the client configuration.

+

For more information, see the [ConfigBuilder] documentation.

+

Trait Implementations§

§

impl Clone for ClientConfig

§

fn clone(&self) -> ClientConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ClientConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ClientConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/sidebar-items.js b/actix_tls/connect/rustls_0_20/sidebar-items.js new file mode 100644 index 00000000..5564ad8e --- /dev/null +++ b/actix_tls/connect/rustls_0_20/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["native_roots_cert_store","webpki_roots_cert_store"],"mod":["reexports"],"struct":["TlsConnector","TlsConnectorService"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/struct.TlsConnector.html b/actix_tls/connect/rustls_0_20/struct.TlsConnector.html new file mode 100644 index 00000000..59e82bad --- /dev/null +++ b/actix_tls/connect/rustls_0_20/struct.TlsConnector.html @@ -0,0 +1,36 @@ +TlsConnector in actix_tls::connect::rustls_0_20 - Rust
actix_tls::connect::rustls_0_20

Struct TlsConnector

source
pub struct TlsConnector { /* private fields */ }
Expand description

Connector service factory using rustls.

+

Implementations§

source§

impl TlsConnector

source

pub fn new(connector: Arc<ClientConfig>) -> Self

Constructs new connector service factory from a rustls client configuration.

+
source

pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService

Constructs new connector service from a rustls client configuration.

+

Trait Implementations§

source§

impl Clone for TlsConnector

source§

fn clone(&self) -> TlsConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_20/struct.TlsConnectorService.html b/actix_tls/connect/rustls_0_20/struct.TlsConnectorService.html new file mode 100644 index 00000000..5621de73 --- /dev/null +++ b/actix_tls/connect/rustls_0_20/struct.TlsConnectorService.html @@ -0,0 +1,31 @@ +TlsConnectorService in actix_tls::connect::rustls_0_20 - Rust
actix_tls::connect::rustls_0_20

Struct TlsConnectorService

source
pub struct TlsConnectorService { /* private fields */ }
Expand description

Connector service using rustls.

+

Trait Implementations§

source§

impl Clone for TlsConnectorService

source§

fn clone(&self) -> TlsConnectorService

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/fn.native_roots_cert_store.html b/actix_tls/connect/rustls_0_21/fn.native_roots_cert_store.html new file mode 100644 index 00000000..8f3ff515 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/fn.native_roots_cert_store.html @@ -0,0 +1,3 @@ +native_roots_cert_store in actix_tls::connect::rustls_0_21 - Rust
actix_tls::connect::rustls_0_21

Function native_roots_cert_store

source
pub fn native_roots_cert_store() -> Result<RootCertStore>
Expand description

Returns root certificates via rustls-native-certs crate as a rustls certificate store.

+

See rustls_native_certs::load_native_certs() for more info on behavior and errors.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/fn.webpki_roots_cert_store.html b/actix_tls/connect/rustls_0_21/fn.webpki_roots_cert_store.html new file mode 100644 index 00000000..76832a00 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/fn.webpki_roots_cert_store.html @@ -0,0 +1,2 @@ +webpki_roots_cert_store in actix_tls::connect::rustls_0_21 - Rust
actix_tls::connect::rustls_0_21

Function webpki_roots_cert_store

source
pub fn webpki_roots_cert_store() -> RootCertStore
Expand description

Returns standard root certificates from webpki-roots crate as a rustls certificate store.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/index.html b/actix_tls/connect/rustls_0_21/index.html new file mode 100644 index 00000000..a8774134 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::rustls_0_21 - Rust
actix_tls::connect

Module rustls_0_21

source
Expand description

Rustls based connector service.

+

See TlsConnector for main connector service factory docs.

+

Modules§

  • Re-exports from the rustls v0.21 ecosystem that are useful for connectors.

Structs§

Functions§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/reexports/constant.TLS_SERVER_ROOTS.html b/actix_tls/connect/rustls_0_21/reexports/constant.TLS_SERVER_ROOTS.html new file mode 100644 index 00000000..14183c14 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/reexports/constant.TLS_SERVER_ROOTS.html @@ -0,0 +1 @@ +TLS_SERVER_ROOTS in actix_tls::connect::rustls_0_21::reexports - Rust
actix_tls::connect::rustls_0_21::reexports

Constant TLS_SERVER_ROOTS

pub const TLS_SERVER_ROOTS: &'static [TrustAnchor<'static>];
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/reexports/index.html b/actix_tls/connect/rustls_0_21/reexports/index.html new file mode 100644 index 00000000..d84dca9c --- /dev/null +++ b/actix_tls/connect/rustls_0_21/reexports/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::rustls_0_21::reexports - Rust
actix_tls::connect::rustls_0_21

Module reexports

source
Expand description

Re-exports from the rustls v0.21 ecosystem that are useful for connectors.

+

Structs§

  • A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.
  • Common configuration for (typically) all connections made by a program.

Constants§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/reexports/sidebar-items.js b/actix_tls/connect/rustls_0_21/reexports/sidebar-items.js new file mode 100644 index 00000000..33872f1f --- /dev/null +++ b/actix_tls/connect/rustls_0_21/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":["TLS_SERVER_ROOTS"],"struct":["AsyncTlsStream","ClientConfig"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/reexports/struct.AsyncTlsStream.html b/actix_tls/connect/rustls_0_21/reexports/struct.AsyncTlsStream.html new file mode 100644 index 00000000..28169f84 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/reexports/struct.AsyncTlsStream.html @@ -0,0 +1,49 @@ +AsyncTlsStream in actix_tls::connect::rustls_0_21::reexports - Rust
actix_tls::connect::rustls_0_21::reexports

Struct AsyncTlsStream

pub struct AsyncTlsStream<IO> { /* private fields */ }
Expand description

A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.

+

Implementations§

§

impl<IO> TlsStream<IO>

pub fn get_ref(&self) -> (&IO, &ClientConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ClientConnection)

pub fn into_inner(self) -> (IO, ClientConnection)

Trait Implementations§

§

impl<S> AsRawFd for TlsStream<S>
where + S: AsRawFd,

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl<IO> AsyncRead for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_read( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
§

impl<IO> AsyncWrite for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_write( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Note: that it does not guarantee the final data to be sent. +To be cautious, you must manually call flush.

+
§

fn poll_flush( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
§

fn poll_shutdown( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
§

impl<IO> Debug for TlsStream<IO>
where + IO: Debug,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/reexports/struct.ClientConfig.html b/actix_tls/connect/rustls_0_21/reexports/struct.ClientConfig.html new file mode 100644 index 00000000..d1b83247 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/reexports/struct.ClientConfig.html @@ -0,0 +1,60 @@ +ClientConfig in actix_tls::connect::rustls_0_21::reexports - Rust
actix_tls::connect::rustls_0_21::reexports

Struct ClientConfig

pub struct ClientConfig {
+    pub alpn_protocols: Vec<Vec<u8>>,
+    pub resumption: Resumption,
+    pub max_fragment_size: Option<usize>,
+    pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
+    pub enable_sni: bool,
+    pub key_log: Arc<dyn KeyLog>,
+    pub enable_early_data: bool,
+    /* private fields */
+}
Expand description

Common configuration for (typically) all connections made by a program.

+

Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots +from the operating system to add to the RootCertStore passed to with_root_certificates() +(the rustls-native-certs crate is often used for this) may take on the order of a few hundred +milliseconds.

+

These must be created via the ClientConfig::builder() function.

+

§Defaults

+ +

Fields§

§alpn_protocols: Vec<Vec<u8>>

Which ALPN protocols we include in our client hello. +If empty, no ALPN extension is sent.

+
§resumption: Resumption

How and when the client can resume a previous session.

+
§max_fragment_size: Option<usize>

The maximum size of TLS message we’ll emit. If None, we don’t limit TLS +message lengths except to the 2**16 limit specified in the standard.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ClientConnection::new.

+

Setting this value to the TCP MSS may improve latency for stream-y workloads.

+
§client_auth_cert_resolver: Arc<dyn ResolvesClientCert>

How to decide what client auth certificate/keys to use.

+
§enable_sni: bool

Whether to send the Server Name Indication (SNI) extension +during the client handshake.

+

The default is true.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§enable_early_data: bool

Whether to send data on the first flight (“early data”) in +TLS 1.3 handshakes.

+

The default is false.

+

Implementations§

§

impl ClientConfig

pub fn builder() -> ConfigBuilder<ClientConfig, WantsCipherSuites>

Create a builder to build up the client configuration.

+

For more information, see the [ConfigBuilder] documentation.

+

Trait Implementations§

§

impl Clone for ClientConfig

§

fn clone(&self) -> ClientConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ClientConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ClientConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/sidebar-items.js b/actix_tls/connect/rustls_0_21/sidebar-items.js new file mode 100644 index 00000000..5564ad8e --- /dev/null +++ b/actix_tls/connect/rustls_0_21/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["native_roots_cert_store","webpki_roots_cert_store"],"mod":["reexports"],"struct":["TlsConnector","TlsConnectorService"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/struct.TlsConnector.html b/actix_tls/connect/rustls_0_21/struct.TlsConnector.html new file mode 100644 index 00000000..97be6037 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/struct.TlsConnector.html @@ -0,0 +1,36 @@ +TlsConnector in actix_tls::connect::rustls_0_21 - Rust
actix_tls::connect::rustls_0_21

Struct TlsConnector

source
pub struct TlsConnector { /* private fields */ }
Expand description

Connector service factory using rustls.

+

Implementations§

source§

impl TlsConnector

source

pub fn new(connector: Arc<ClientConfig>) -> Self

Constructs new connector service factory from a rustls client configuration.

+
source

pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService

Constructs new connector service from a rustls client configuration.

+

Trait Implementations§

source§

impl Clone for TlsConnector

source§

fn clone(&self) -> TlsConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_21/struct.TlsConnectorService.html b/actix_tls/connect/rustls_0_21/struct.TlsConnectorService.html new file mode 100644 index 00000000..989461a5 --- /dev/null +++ b/actix_tls/connect/rustls_0_21/struct.TlsConnectorService.html @@ -0,0 +1,31 @@ +TlsConnectorService in actix_tls::connect::rustls_0_21 - Rust
actix_tls::connect::rustls_0_21

Struct TlsConnectorService

source
pub struct TlsConnectorService { /* private fields */ }
Expand description

Connector service using rustls.

+

Trait Implementations§

source§

impl Clone for TlsConnectorService

source§

fn clone(&self) -> TlsConnectorService

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/fn.native_roots_cert_store.html b/actix_tls/connect/rustls_0_22/fn.native_roots_cert_store.html new file mode 100644 index 00000000..37f0100b --- /dev/null +++ b/actix_tls/connect/rustls_0_22/fn.native_roots_cert_store.html @@ -0,0 +1,3 @@ +native_roots_cert_store in actix_tls::connect::rustls_0_22 - Rust
actix_tls::connect::rustls_0_22

Function native_roots_cert_store

source
pub fn native_roots_cert_store() -> Result<RootCertStore>
Expand description

Returns root certificates via rustls-native-certs crate as a rustls certificate store.

+

See rustls_native_certs::load_native_certs() for more info on behavior and errors.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/fn.webpki_roots_cert_store.html b/actix_tls/connect/rustls_0_22/fn.webpki_roots_cert_store.html new file mode 100644 index 00000000..15e7a4d4 --- /dev/null +++ b/actix_tls/connect/rustls_0_22/fn.webpki_roots_cert_store.html @@ -0,0 +1,2 @@ +webpki_roots_cert_store in actix_tls::connect::rustls_0_22 - Rust
actix_tls::connect::rustls_0_22

Function webpki_roots_cert_store

source
pub fn webpki_roots_cert_store() -> RootCertStore
Expand description

Returns standard root certificates from webpki-roots crate as a rustls certificate store.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/index.html b/actix_tls/connect/rustls_0_22/index.html new file mode 100644 index 00000000..d58f7be7 --- /dev/null +++ b/actix_tls/connect/rustls_0_22/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::rustls_0_22 - Rust
actix_tls::connect

Module rustls_0_22

source
Expand description

Rustls based connector service.

+

See TlsConnector for main connector service factory docs.

+

Modules§

  • Re-exports from the rustls v0.22 ecosystem that are useful for connectors.

Structs§

Functions§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/reexports/constant.TLS_SERVER_ROOTS.html b/actix_tls/connect/rustls_0_22/reexports/constant.TLS_SERVER_ROOTS.html new file mode 100644 index 00000000..4ecd45b2 --- /dev/null +++ b/actix_tls/connect/rustls_0_22/reexports/constant.TLS_SERVER_ROOTS.html @@ -0,0 +1 @@ +TLS_SERVER_ROOTS in actix_tls::connect::rustls_0_22::reexports - Rust
actix_tls::connect::rustls_0_22::reexports

Constant TLS_SERVER_ROOTS

pub const TLS_SERVER_ROOTS: &'static [TrustAnchor<'static>];
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/reexports/index.html b/actix_tls/connect/rustls_0_22/reexports/index.html new file mode 100644 index 00000000..d433fa9d --- /dev/null +++ b/actix_tls/connect/rustls_0_22/reexports/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::rustls_0_22::reexports - Rust
actix_tls::connect::rustls_0_22

Module reexports

source
Expand description

Re-exports from the rustls v0.22 ecosystem that are useful for connectors.

+

Structs§

  • A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.
  • Common configuration for (typically) all connections made by a program.

Constants§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/reexports/sidebar-items.js b/actix_tls/connect/rustls_0_22/reexports/sidebar-items.js new file mode 100644 index 00000000..33872f1f --- /dev/null +++ b/actix_tls/connect/rustls_0_22/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":["TLS_SERVER_ROOTS"],"struct":["AsyncTlsStream","ClientConfig"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/reexports/struct.AsyncTlsStream.html b/actix_tls/connect/rustls_0_22/reexports/struct.AsyncTlsStream.html new file mode 100644 index 00000000..35081987 --- /dev/null +++ b/actix_tls/connect/rustls_0_22/reexports/struct.AsyncTlsStream.html @@ -0,0 +1,49 @@ +AsyncTlsStream in actix_tls::connect::rustls_0_22::reexports - Rust
actix_tls::connect::rustls_0_22::reexports

Struct AsyncTlsStream

pub struct AsyncTlsStream<IO> { /* private fields */ }
Expand description

A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.

+

Implementations§

§

impl<IO> TlsStream<IO>

pub fn get_ref(&self) -> (&IO, &ClientConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ClientConnection)

pub fn into_inner(self) -> (IO, ClientConnection)

Trait Implementations§

§

impl<S> AsRawFd for TlsStream<S>
where + S: AsRawFd,

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl<IO> AsyncRead for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_read( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
§

impl<IO> AsyncWrite for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_write( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Note: that it does not guarantee the final data to be sent. +To be cautious, you must manually call flush.

+
§

fn poll_flush( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
§

fn poll_shutdown( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
§

impl<IO> Debug for TlsStream<IO>
where + IO: Debug,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/reexports/struct.ClientConfig.html b/actix_tls/connect/rustls_0_22/reexports/struct.ClientConfig.html new file mode 100644 index 00000000..c1630095 --- /dev/null +++ b/actix_tls/connect/rustls_0_22/reexports/struct.ClientConfig.html @@ -0,0 +1,84 @@ +ClientConfig in actix_tls::connect::rustls_0_22::reexports - Rust
actix_tls::connect::rustls_0_22::reexports

Struct ClientConfig

pub struct ClientConfig {
+    pub alpn_protocols: Vec<Vec<u8>>,
+    pub resumption: Resumption,
+    pub max_fragment_size: Option<usize>,
+    pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
+    pub enable_sni: bool,
+    pub key_log: Arc<dyn KeyLog>,
+    pub enable_secret_extraction: bool,
+    pub enable_early_data: bool,
+    /* private fields */
+}
Expand description

Common configuration for (typically) all connections made by a program.

+

Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots +from the operating system to add to the RootCertStore passed to with_root_certificates() +(the rustls-native-certs crate is often used for this) may take on the order of a few hundred +milliseconds.

+

These must be created via the ClientConfig::builder() or ClientConfig::builder_with_provider() +function.

+

§Defaults

+ +

Fields§

§alpn_protocols: Vec<Vec<u8>>

Which ALPN protocols we include in our client hello. +If empty, no ALPN extension is sent.

+
§resumption: Resumption

How and when the client can resume a previous session.

+
§max_fragment_size: Option<usize>

The maximum size of plaintext input to be emitted in a single TLS record. +A value of None is equivalent to the TLS maximum of 16 kB.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ClientConnection::new.

+

Setting this value to a little less than the TCP MSS may improve latency +for stream-y workloads.

+
§client_auth_cert_resolver: Arc<dyn ResolvesClientCert>

How to decide what client auth certificate/keys to use.

+
§enable_sni: bool

Whether to send the Server Name Indication (SNI) extension +during the client handshake.

+

The default is true.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§enable_secret_extraction: bool

Allows traffic secrets to be extracted after the handshake, +e.g. for kTLS setup.

+
§enable_early_data: bool

Whether to send data on the first flight (“early data”) in +TLS 1.3 handshakes.

+

The default is false.

+

Implementations§

§

impl ClientConfig

pub fn builder() -> ConfigBuilder<ClientConfig, WantsVerifier>

Create a builder for a client configuration with the default +[CryptoProvider]: [crypto::ring::default_provider] and safe ciphersuite and +protocol defaults.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_protocol_versions( + versions: &[&'static SupportedProtocolVersion], +) -> ConfigBuilder<ClientConfig, WantsVerifier>

Create a builder for a client configuration with the default +[CryptoProvider]: [crypto::ring::default_provider], safe ciphersuite defaults and +the provided protocol versions.

+

Panics if provided an empty slice of supported versions.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_provider( + provider: Arc<CryptoProvider>, +) -> ConfigBuilder<ClientConfig, WantsVersions>

Create a builder for a client configuration with a specific [CryptoProvider].

+

This will use the provider’s configured ciphersuites. You must additionally choose +which protocol versions to enable, using with_protocol_versions or +with_safe_default_protocol_versions and handling the Result in case a protocol +version is not supported by the provider’s ciphersuites.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn dangerous(&mut self) -> DangerousClientConfig<'_>

Access configuration options whose use is dangerous and requires +extra care.

+

Trait Implementations§

§

impl Clone for ClientConfig

§

fn clone(&self) -> ClientConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ClientConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ClientConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/sidebar-items.js b/actix_tls/connect/rustls_0_22/sidebar-items.js new file mode 100644 index 00000000..5564ad8e --- /dev/null +++ b/actix_tls/connect/rustls_0_22/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["native_roots_cert_store","webpki_roots_cert_store"],"mod":["reexports"],"struct":["TlsConnector","TlsConnectorService"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/struct.TlsConnector.html b/actix_tls/connect/rustls_0_22/struct.TlsConnector.html new file mode 100644 index 00000000..934ec512 --- /dev/null +++ b/actix_tls/connect/rustls_0_22/struct.TlsConnector.html @@ -0,0 +1,36 @@ +TlsConnector in actix_tls::connect::rustls_0_22 - Rust
actix_tls::connect::rustls_0_22

Struct TlsConnector

source
pub struct TlsConnector { /* private fields */ }
Expand description

Connector service factory using rustls.

+

Implementations§

source§

impl TlsConnector

source

pub fn new(connector: Arc<ClientConfig>) -> Self

Constructs new connector service factory from a rustls client configuration.

+
source

pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService

Constructs new connector service from a rustls client configuration.

+

Trait Implementations§

source§

impl Clone for TlsConnector

source§

fn clone(&self) -> TlsConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_22/struct.TlsConnectorService.html b/actix_tls/connect/rustls_0_22/struct.TlsConnectorService.html new file mode 100644 index 00000000..cfa09444 --- /dev/null +++ b/actix_tls/connect/rustls_0_22/struct.TlsConnectorService.html @@ -0,0 +1,31 @@ +TlsConnectorService in actix_tls::connect::rustls_0_22 - Rust
actix_tls::connect::rustls_0_22

Struct TlsConnectorService

source
pub struct TlsConnectorService { /* private fields */ }
Expand description

Connector service using rustls.

+

Trait Implementations§

source§

impl Clone for TlsConnectorService

source§

fn clone(&self) -> TlsConnectorService

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/fn.native_roots_cert_store.html b/actix_tls/connect/rustls_0_23/fn.native_roots_cert_store.html new file mode 100644 index 00000000..c1286901 --- /dev/null +++ b/actix_tls/connect/rustls_0_23/fn.native_roots_cert_store.html @@ -0,0 +1,3 @@ +native_roots_cert_store in actix_tls::connect::rustls_0_23 - Rust
actix_tls::connect::rustls_0_23

Function native_roots_cert_store

source
pub fn native_roots_cert_store() -> Result<RootCertStore>
Expand description

Returns root certificates via rustls-native-certs crate as a rustls certificate store.

+

See rustls_native_certs::load_native_certs() for more info on behavior and errors.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/fn.webpki_roots_cert_store.html b/actix_tls/connect/rustls_0_23/fn.webpki_roots_cert_store.html new file mode 100644 index 00000000..349fb4c4 --- /dev/null +++ b/actix_tls/connect/rustls_0_23/fn.webpki_roots_cert_store.html @@ -0,0 +1,2 @@ +webpki_roots_cert_store in actix_tls::connect::rustls_0_23 - Rust
actix_tls::connect::rustls_0_23

Function webpki_roots_cert_store

source
pub fn webpki_roots_cert_store() -> RootCertStore
Expand description

Returns standard root certificates from webpki-roots crate as a rustls certificate store.

+
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/index.html b/actix_tls/connect/rustls_0_23/index.html new file mode 100644 index 00000000..69c02157 --- /dev/null +++ b/actix_tls/connect/rustls_0_23/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::rustls_0_23 - Rust
actix_tls::connect

Module rustls_0_23

source
Expand description

Rustls based connector service.

+

See TlsConnector for main connector service factory docs.

+

Modules§

  • Re-exports from the rustls v0.23 ecosystem that are useful for connectors.

Structs§

Functions§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/reexports/constant.TLS_SERVER_ROOTS.html b/actix_tls/connect/rustls_0_23/reexports/constant.TLS_SERVER_ROOTS.html new file mode 100644 index 00000000..ceec4b67 --- /dev/null +++ b/actix_tls/connect/rustls_0_23/reexports/constant.TLS_SERVER_ROOTS.html @@ -0,0 +1 @@ +TLS_SERVER_ROOTS in actix_tls::connect::rustls_0_23::reexports - Rust
actix_tls::connect::rustls_0_23::reexports

Constant TLS_SERVER_ROOTS

pub const TLS_SERVER_ROOTS: &'static [TrustAnchor<'static>];
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/reexports/index.html b/actix_tls/connect/rustls_0_23/reexports/index.html new file mode 100644 index 00000000..bba1d60e --- /dev/null +++ b/actix_tls/connect/rustls_0_23/reexports/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::rustls_0_23::reexports - Rust
actix_tls::connect::rustls_0_23

Module reexports

source
Expand description

Re-exports from the rustls v0.23 ecosystem that are useful for connectors.

+

Structs§

  • A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.
  • Common configuration for (typically) all connections made by a program.

Constants§

\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/reexports/sidebar-items.js b/actix_tls/connect/rustls_0_23/reexports/sidebar-items.js new file mode 100644 index 00000000..33872f1f --- /dev/null +++ b/actix_tls/connect/rustls_0_23/reexports/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":["TLS_SERVER_ROOTS"],"struct":["AsyncTlsStream","ClientConfig"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/reexports/struct.AsyncTlsStream.html b/actix_tls/connect/rustls_0_23/reexports/struct.AsyncTlsStream.html new file mode 100644 index 00000000..a850cb40 --- /dev/null +++ b/actix_tls/connect/rustls_0_23/reexports/struct.AsyncTlsStream.html @@ -0,0 +1,51 @@ +AsyncTlsStream in actix_tls::connect::rustls_0_23::reexports - Rust
actix_tls::connect::rustls_0_23::reexports

Struct AsyncTlsStream

pub struct AsyncTlsStream<IO> { /* private fields */ }
Expand description

A wrapper around an underlying raw stream which implements the TLS or SSL +protocol.

+

Implementations§

§

impl<IO> TlsStream<IO>

pub fn get_ref(&self) -> (&IO, &ClientConnection)

pub fn get_mut(&mut self) -> (&mut IO, &mut ClientConnection)

pub fn into_inner(self) -> (IO, ClientConnection)

Trait Implementations§

§

impl<S> AsRawFd for TlsStream<S>
where + S: AsRawFd,

§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
§

impl<IO> AsyncRead for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_read( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, +) -> Poll<Result<(), Error>>

Attempts to read from the AsyncRead into buf. Read more
§

impl<IO> AsyncWrite for TlsStream<IO>
where + IO: AsyncRead + AsyncWrite + Unpin,

§

fn poll_write( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + buf: &[u8], +) -> Poll<Result<usize, Error>>

Note: that it does not guarantee the final data to be sent. +To be cautious, you must manually call flush.

+
§

fn poll_write_vectored( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], +) -> Poll<Result<usize, Error>>

Note: that it does not guarantee the final data to be sent. +To be cautious, you must manually call flush.

+
§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored +implementation. Read more
§

fn poll_flush( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Attempts to flush the object, ensuring that any buffered data reach +their destination. Read more
§

fn poll_shutdown( + self: Pin<&mut TlsStream<IO>>, + cx: &mut Context<'_>, +) -> Poll<Result<(), Error>>

Initiates or attempts to shut down this writer, returning success when +the I/O connection has completely shut down. Read more
§

impl<IO> Debug for TlsStream<IO>
where + IO: Debug,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<IO> Freeze for TlsStream<IO>
where + IO: Freeze,

§

impl<IO> !RefUnwindSafe for TlsStream<IO>

§

impl<IO> Send for TlsStream<IO>
where + IO: Send,

§

impl<IO> Sync for TlsStream<IO>
where + IO: Sync,

§

impl<IO> Unpin for TlsStream<IO>
where + IO: Unpin,

§

impl<IO> !UnwindSafe for TlsStream<IO>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/reexports/struct.ClientConfig.html b/actix_tls/connect/rustls_0_23/reexports/struct.ClientConfig.html new file mode 100644 index 00000000..aa7c196b --- /dev/null +++ b/actix_tls/connect/rustls_0_23/reexports/struct.ClientConfig.html @@ -0,0 +1,137 @@ +ClientConfig in actix_tls::connect::rustls_0_23::reexports - Rust
actix_tls::connect::rustls_0_23::reexports

Struct ClientConfig

pub struct ClientConfig {
+    pub alpn_protocols: Vec<Vec<u8>>,
+    pub resumption: Resumption,
+    pub max_fragment_size: Option<usize>,
+    pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
+    pub enable_sni: bool,
+    pub key_log: Arc<dyn KeyLog>,
+    pub enable_secret_extraction: bool,
+    pub enable_early_data: bool,
+    pub time_provider: Arc<dyn TimeProvider>,
+    pub cert_decompressors: Vec<&'static dyn CertDecompressor>,
+    pub cert_compressors: Vec<&'static dyn CertCompressor>,
+    pub cert_compression_cache: Arc<CompressionCache>,
+    /* private fields */
+}
Expand description

Common configuration for (typically) all connections made by a program.

+

Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots +from the operating system to add to the RootCertStore passed to with_root_certificates() +(the rustls-native-certs crate is often used for this) may take on the order of a few hundred +milliseconds.

+

These must be created via the ClientConfig::builder() or ClientConfig::builder_with_provider() +function.

+

Note that using [ConfigBuilder<ClientConfig, WantsVersions>::with_ech()] will produce a common +configuration specific to the provided [crate::client::EchConfig] that may not be appropriate +for all connections made by the program. In this case the configuration should only be shared +by connections intended for domains that offer the provided [crate::client::EchConfig] in +their DNS zone.

+

§Defaults

+ +

Fields§

§alpn_protocols: Vec<Vec<u8>>

Which ALPN protocols we include in our client hello. +If empty, no ALPN extension is sent.

+
§resumption: Resumption

How and when the client can resume a previous session.

+
§max_fragment_size: Option<usize>

The maximum size of plaintext input to be emitted in a single TLS record. +A value of None is equivalent to the TLS maximum of 16 kB.

+

rustls enforces an arbitrary minimum of 32 bytes for this field. +Out of range values are reported as errors from ClientConnection::new.

+

Setting this value to a little less than the TCP MSS may improve latency +for stream-y workloads.

+
§client_auth_cert_resolver: Arc<dyn ResolvesClientCert>

How to decide what client auth certificate/keys to use.

+
§enable_sni: bool

Whether to send the Server Name Indication (SNI) extension +during the client handshake.

+

The default is true.

+
§key_log: Arc<dyn KeyLog>

How to output key material for debugging. The default +does nothing.

+
§enable_secret_extraction: bool

Allows traffic secrets to be extracted after the handshake, +e.g. for kTLS setup.

+
§enable_early_data: bool

Whether to send data on the first flight (“early data”) in +TLS 1.3 handshakes.

+

The default is false.

+
§time_provider: Arc<dyn TimeProvider>

Provides the current system time

+
§cert_decompressors: Vec<&'static dyn CertDecompressor>

How to decompress the server’s certificate chain.

+

If this is non-empty, the RFC8779 certificate compression +extension is offered, and any compressed certificates are +transparently decompressed during the handshake.

+

This only applies to TLS1.3 connections. It is ignored for +TLS1.2 connections.

+
§cert_compressors: Vec<&'static dyn CertCompressor>

How to compress the client’s certificate chain.

+

If a server supports this extension, and advertises support +for one of the compression algorithms included here, the +client certificate will be compressed according to RFC8779.

+

This only applies to TLS1.3 connections. It is ignored for +TLS1.2 connections.

+
§cert_compression_cache: Arc<CompressionCache>

Caching for compressed certificates.

+

This is optional: [compress::CompressionCache::Disabled] gives +a cache that does no caching.

+

Implementations§

§

impl ClientConfig

pub fn builder() -> ConfigBuilder<ClientConfig, WantsVerifier>

Create a builder for a client configuration with +[the process-default CryptoProvider][CryptoProvider#using-the-per-process-default-cryptoprovider] +and safe protocol version defaults.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_protocol_versions( + versions: &[&'static SupportedProtocolVersion], +) -> ConfigBuilder<ClientConfig, WantsVerifier>

Create a builder for a client configuration with +[the process-default CryptoProvider][CryptoProvider#using-the-per-process-default-cryptoprovider] +and the provided protocol versions.

+

Panics if

+
    +
  • the supported versions are not compatible with the provider (eg. +the combination of ciphersuites supported by the provider and supported +versions lead to zero cipher suites being usable),
  • +
  • if a CryptoProvider cannot be resolved using a combination of +the crate features and process default.
  • +
+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_provider( + provider: Arc<CryptoProvider>, +) -> ConfigBuilder<ClientConfig, WantsVersions>

Create a builder for a client configuration with a specific [CryptoProvider].

+

This will use the provider’s configured ciphersuites. You must additionally choose +which protocol versions to enable, using with_protocol_versions or +with_safe_default_protocol_versions and handling the Result in case a protocol +version is not supported by the provider’s ciphersuites.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn builder_with_details( + provider: Arc<CryptoProvider>, + time_provider: Arc<dyn TimeProvider>, +) -> ConfigBuilder<ClientConfig, WantsVersions>

Create a builder for a client configuration with no default implementation details.

+

This API must be used by no_std users.

+

You must provide a specific [TimeProvider].

+

You must provide a specific [CryptoProvider].

+

This will use the provider’s configured ciphersuites. You must additionally choose +which protocol versions to enable, using with_protocol_versions or +with_safe_default_protocol_versions and handling the Result in case a protocol +version is not supported by the provider’s ciphersuites.

+

For more information, see the [ConfigBuilder] documentation.

+

pub fn fips(&self) -> bool

Return true if connections made with this ClientConfig will +operate in FIPS mode.

+

This is different from [CryptoProvider::fips()]: [CryptoProvider::fips()] +is concerned only with cryptography, whereas this also covers TLS-level +configuration that NIST recommends, as well as ECH HPKE suites if applicable.

+

pub fn crypto_provider(&self) -> &Arc<CryptoProvider>

Return the crypto provider used to construct this client configuration.

+

pub fn dangerous(&mut self) -> DangerousClientConfig<'_>

Access configuration options whose use is dangerous and requires +extra care.

+

Trait Implementations§

§

impl Clone for ClientConfig

§

fn clone(&self) -> ClientConfig

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for ClientConfig

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl ConfigSide for ClientConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/sidebar-items.js b/actix_tls/connect/rustls_0_23/sidebar-items.js new file mode 100644 index 00000000..5564ad8e --- /dev/null +++ b/actix_tls/connect/rustls_0_23/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["native_roots_cert_store","webpki_roots_cert_store"],"mod":["reexports"],"struct":["TlsConnector","TlsConnectorService"]}; \ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/struct.TlsConnector.html b/actix_tls/connect/rustls_0_23/struct.TlsConnector.html new file mode 100644 index 00000000..2c3a1e4c --- /dev/null +++ b/actix_tls/connect/rustls_0_23/struct.TlsConnector.html @@ -0,0 +1,36 @@ +TlsConnector in actix_tls::connect::rustls_0_23 - Rust
actix_tls::connect::rustls_0_23

Struct TlsConnector

source
pub struct TlsConnector { /* private fields */ }
Expand description

Connector service factory using rustls.

+

Implementations§

source§

impl TlsConnector

source

pub fn new(connector: Arc<ClientConfig>) -> Self

Constructs new connector service factory from a rustls client configuration.

+
source

pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService

Constructs new connector service from a rustls client configuration.

+

Trait Implementations§

source§

impl Clone for TlsConnector

source§

fn clone(&self) -> TlsConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/rustls_0_23/struct.TlsConnectorService.html b/actix_tls/connect/rustls_0_23/struct.TlsConnectorService.html new file mode 100644 index 00000000..23e84c87 --- /dev/null +++ b/actix_tls/connect/rustls_0_23/struct.TlsConnectorService.html @@ -0,0 +1,31 @@ +TlsConnectorService in actix_tls::connect::rustls_0_23 - Rust
actix_tls::connect::rustls_0_23

Struct TlsConnectorService

source
pub struct TlsConnectorService { /* private fields */ }
Expand description

Connector service using rustls.

+

Trait Implementations§

source§

impl Clone for TlsConnectorService

source§

fn clone(&self) -> TlsConnectorService

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/sidebar-items.js b/actix_tls/connect/sidebar-items.js new file mode 100644 index 00000000..a413b4ec --- /dev/null +++ b/actix_tls/connect/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["ConnectError"],"mod":["native_tls","openssl","rustls_0_20","rustls_0_21","rustls_0_22","rustls_0_23","tcp"],"struct":["ConnectInfo","Connection","Connector","ConnectorService","Resolver","ResolverService"],"trait":["Host","Resolve"]}; \ No newline at end of file diff --git a/actix_tls/connect/struct.ConnectInfo.html b/actix_tls/connect/struct.ConnectInfo.html new file mode 100644 index 00000000..a652299b --- /dev/null +++ b/actix_tls/connect/struct.ConnectInfo.html @@ -0,0 +1,69 @@ +ConnectInfo in actix_tls::connect - Rust
actix_tls::connect

Struct ConnectInfo

source
pub struct ConnectInfo<R> { /* private fields */ }
Expand description

Connection request information.

+

May contain known/pre-resolved socket address(es) or a host that needs resolving with DNS.

+

Implementations§

source§

impl<R: Host> ConnectInfo<R>

source

pub fn new(request: R) -> ConnectInfo<R>

Constructs new connection info using a request.

+
source

pub fn with_addr(request: R, addr: SocketAddr) -> ConnectInfo<R>

Constructs new connection info from request and known socket address.

+

Since socket address is known, Connector will skip the DNS +resolution step.

+
source

pub fn set_port(self, port: u16) -> Self

Set connection port.

+

If request provided a port, this will override it.

+
source

pub fn set_addr(self, addr: impl Into<Option<SocketAddr>>) -> Self

Set connection socket address.

+
source

pub fn set_addrs<I>(self, addrs: I) -> Self
where + I: IntoIterator<Item = SocketAddr>,

Set list of addresses.

+
source

pub fn set_local_addr(self, addr: impl Into<IpAddr>) -> Self

Set local address to connection with.

+

Useful in situations where the IP address bound to a particular network interface is known. +This would make sure the socket is opened through that interface.

+
source

pub fn request(&self) -> &R

Returns a reference to the connection request.

+
source

pub fn hostname(&self) -> &str

Returns request hostname.

+
source

pub fn port(&self) -> u16

Returns request port.

+
source

pub fn addrs( + &self, +) -> impl Iterator<Item = SocketAddr> + ExactSizeIterator + FusedIterator + Clone + Debug + '_

Get borrowed iterator of resolved request addresses.

+
§Examples
+
let addr = SocketAddr::from(([127, 0, 0, 1], 4242));
+
+let conn = ConnectInfo::new("localhost");
+let mut addrs = conn.addrs();
+assert!(addrs.next().is_none());
+
+let conn = ConnectInfo::with_addr("localhost", addr);
+let mut addrs = conn.addrs();
+assert_eq!(addrs.next().unwrap(), addr);
+
source

pub fn take_addrs( + &mut self, +) -> impl Iterator<Item = SocketAddr> + ExactSizeIterator + FusedIterator + Clone + Debug + 'static

Take owned iterator resolved request addresses.

+
§Examples
+
let addr = SocketAddr::from(([127, 0, 0, 1], 4242));
+
+let mut conn = ConnectInfo::new("localhost");
+let mut addrs = conn.take_addrs();
+assert!(addrs.next().is_none());
+
+let mut conn = ConnectInfo::with_addr("localhost", addr);
+let mut addrs = conn.take_addrs();
+assert_eq!(addrs.next().unwrap(), addr);
+

Trait Implementations§

source§

impl<R: Debug> Debug for ConnectInfo<R>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<R: Host> Display for ConnectInfo<R>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<R: Host> From<R> for ConnectInfo<R>

source§

fn from(addr: R) -> Self

Converts to this type from the input type.
source§

impl<R: Hash> Hash for ConnectInfo<R>

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.6.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + H: Hasher, + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<R: PartialEq> PartialEq for ConnectInfo<R>

source§

fn eq(&self, other: &ConnectInfo<R>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.6.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl<R: Host> Service<ConnectInfo<R>> for ConnectorService

source§

type Response = Connection<R, TcpStream>

Responses given by the service.
source§

type Error = ConnectError

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectServiceResponse<R>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: ConnectInfo<R>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R: Host> Service<ConnectInfo<R>> for ResolverService

source§

type Response = ConnectInfo<R>

Responses given by the service.
source§

type Error = ConnectError

Errors produced by the service when polling readiness or executing call.
source§

type Future = ResolverFut<R>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: ConnectInfo<R>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R: Host> Service<ConnectInfo<R>> for TcpConnectorService

source§

type Response = Connection<R, TcpStream>

Responses given by the service.
source§

type Error = ConnectError

Errors produced by the service when polling readiness or executing call.
source§

type Future = TcpConnectorFut<R>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: ConnectInfo<R>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R: Host> ServiceFactory<ConnectInfo<R>> for Connector

source§

type Response = Connection<R, TcpStream>

Responses given by the created services.
source§

type Error = ConnectError

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = ConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Connector as ServiceFactory<ConnectInfo<R>>>::Service, <Connector as ServiceFactory<ConnectInfo<R>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R: Host> ServiceFactory<ConnectInfo<R>> for Resolver

source§

type Response = ConnectInfo<R>

Responses given by the created services.
source§

type Error = ConnectError

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = ResolverService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Resolver as ServiceFactory<ConnectInfo<R>>>::Service, <Resolver as ServiceFactory<ConnectInfo<R>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R: Host> ServiceFactory<ConnectInfo<R>> for TcpConnector

source§

type Response = Connection<R, TcpStream>

Responses given by the created services.
source§

type Error = ConnectError

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TcpConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TcpConnector as ServiceFactory<ConnectInfo<R>>>::Service, <TcpConnector as ServiceFactory<ConnectInfo<R>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R: Eq> Eq for ConnectInfo<R>

source§

impl<R> StructuralPartialEq for ConnectInfo<R>

Auto Trait Implementations§

§

impl<R> Freeze for ConnectInfo<R>
where + R: Freeze,

§

impl<R> RefUnwindSafe for ConnectInfo<R>
where + R: RefUnwindSafe,

§

impl<R> Send for ConnectInfo<R>
where + R: Send,

§

impl<R> Sync for ConnectInfo<R>
where + R: Sync,

§

impl<R> Unpin for ConnectInfo<R>
where + R: Unpin,

§

impl<R> UnwindSafe for ConnectInfo<R>
where + R: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/struct.Connection.html b/actix_tls/connect/struct.Connection.html new file mode 100644 index 00000000..92750820 --- /dev/null +++ b/actix_tls/connect/struct.Connection.html @@ -0,0 +1,61 @@ +Connection in actix_tls::connect - Rust
actix_tls::connect

Struct Connection

source
pub struct Connection<R, IO> { /* private fields */ }
Expand description

Wraps underlying I/O and the connection request that initiated it.

+

Implementations§

source§

impl<R, IO> Connection<R, IO>

source

pub fn new(req: R, io: IO) -> Self

Construct new Connection from request and IO parts.

+
source§

impl<R, IO> Connection<R, IO>

source

pub fn into_parts(self) -> (IO, R)

Deconstructs into IO and request parts.

+
source

pub fn replace_io<IO2>(self, io: IO2) -> (IO, Connection<R, IO2>)

Replaces underlying IO, returning old IO and new Connection.

+
source

pub fn io_ref(&self) -> &IO

Returns a shared reference to the underlying IO.

+
source

pub fn io_mut(&mut self) -> &mut IO

Returns a mutable reference to the underlying IO.

+
source

pub fn request(&self) -> &R

Returns a reference to the connection request.

+
source§

impl<R: Host, IO> Connection<R, IO>

source

pub fn hostname(&self) -> &str

Returns hostname.

+

Trait Implementations§

source§

impl<R: Debug, IO: Debug> Debug for Connection<R, IO>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<R, IO> Deref for Connection<R, IO>

source§

type Target = IO

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<R, IO> DerefMut for Connection<R, IO>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

The native-tls connector is both it’s ServiceFactory and Service impl type. +As the factory and service share the same type and state.

+
source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = Pin<Box<dyn Future<Output = Result<<TlsConnector as Service<Connection<R, IO>>>::Response, <TlsConnector as Service<Connection<R, IO>>>::Error>>>>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, stream: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, SslStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, stream: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where + R: Host, + IO: ActixStream,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the service.
source§

type Error = Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectFut<R, IO>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, connection: Connection<R, IO>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, SslStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + R: Host, + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl<R: Host, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where + IO: ActixStream + 'static,

source§

type Response = Connection<R, TlsStream<IO>>

Responses given by the created services.
source§

type Error = Error

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TlsConnector

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TlsConnector as ServiceFactory<Connection<R, IO>>>::Service, <TlsConnector as ServiceFactory<Connection<R, IO>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

§

impl<R, IO> Freeze for Connection<R, IO>
where + R: Freeze, + IO: Freeze,

§

impl<R, IO> RefUnwindSafe for Connection<R, IO>
where + R: RefUnwindSafe, + IO: RefUnwindSafe,

§

impl<R, IO> Send for Connection<R, IO>
where + R: Send, + IO: Send,

§

impl<R, IO> Sync for Connection<R, IO>
where + R: Sync, + IO: Sync,

§

impl<R, IO> Unpin for Connection<R, IO>
where + R: Unpin, + IO: Unpin,

§

impl<R, IO> UnwindSafe for Connection<R, IO>
where + R: UnwindSafe, + IO: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/struct.Connector.html b/actix_tls/connect/struct.Connector.html new file mode 100644 index 00000000..409ff158 --- /dev/null +++ b/actix_tls/connect/struct.Connector.html @@ -0,0 +1,36 @@ +Connector in actix_tls::connect - Rust
actix_tls::connect

Struct Connector

source
pub struct Connector { /* private fields */ }
Expand description

Combined resolver and TCP connector service factory.

+

Used to create ConnectorServices which receive connection information, resolve DNS if +required, and return a TCP stream.

+

Implementations§

source§

impl Connector

source

pub fn new(resolver: Resolver) -> Self

Constructs new connector factory with the given resolver.

+
source

pub fn service(&self) -> ConnectorService

Build connector service.

+

Trait Implementations§

source§

impl Clone for Connector

source§

fn clone(&self) -> Connector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for Connector

source§

fn default() -> Connector

Returns the “default value” for a type. Read more
source§

impl<R: Host> ServiceFactory<ConnectInfo<R>> for Connector

source§

type Response = Connection<R, TcpStream>

Responses given by the created services.
source§

type Error = ConnectError

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = ConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Connector as ServiceFactory<ConnectInfo<R>>>::Service, <Connector as ServiceFactory<ConnectInfo<R>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/struct.ConnectorService.html b/actix_tls/connect/struct.ConnectorService.html new file mode 100644 index 00000000..368acf6b --- /dev/null +++ b/actix_tls/connect/struct.ConnectorService.html @@ -0,0 +1,31 @@ +ConnectorService in actix_tls::connect - Rust
actix_tls::connect

Struct ConnectorService

source
pub struct ConnectorService { /* private fields */ }
Expand description

Combined resolver and TCP connector service.

+

Service implementation receives connection information, resolves DNS if required, and returns +a TCP stream.

+

Trait Implementations§

source§

impl Clone for ConnectorService

source§

fn clone(&self) -> ConnectorService

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for ConnectorService

source§

fn default() -> ConnectorService

Returns the “default value” for a type. Read more
source§

impl<R: Host> Service<ConnectInfo<R>> for ConnectorService

source§

type Response = Connection<R, TcpStream>

Responses given by the service.
source§

type Error = ConnectError

Errors produced by the service when polling readiness or executing call.
source§

type Future = ConnectServiceResponse<R>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: ConnectInfo<R>) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/struct.Resolver.html b/actix_tls/connect/struct.Resolver.html new file mode 100644 index 00000000..4c7e486b --- /dev/null +++ b/actix_tls/connect/struct.Resolver.html @@ -0,0 +1,34 @@ +Resolver in actix_tls::connect - Rust
actix_tls::connect

Struct Resolver

source
pub struct Resolver { /* private fields */ }
Expand description

DNS resolver service factory.

+

Implementations§

source§

impl Resolver

source

pub fn custom(resolver: impl Resolve + 'static) -> Self

Constructs a new resolver factory with a custom resolver.

+
source

pub fn service(&self) -> ResolverService

Returns a new resolver service.

+

Trait Implementations§

source§

impl Clone for Resolver

source§

fn clone(&self) -> Resolver

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for Resolver

source§

fn default() -> Resolver

Returns the “default value” for a type. Read more
source§

impl<R: Host> ServiceFactory<ConnectInfo<R>> for Resolver

source§

type Response = ConnectInfo<R>

Responses given by the created services.
source§

type Error = ConnectError

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = ResolverService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<Resolver as ServiceFactory<ConnectInfo<R>>>::Service, <Resolver as ServiceFactory<ConnectInfo<R>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/struct.ResolverService.html b/actix_tls/connect/struct.ResolverService.html new file mode 100644 index 00000000..79384ab3 --- /dev/null +++ b/actix_tls/connect/struct.ResolverService.html @@ -0,0 +1,30 @@ +ResolverService in actix_tls::connect - Rust
actix_tls::connect

Struct ResolverService

source
pub struct ResolverService { /* private fields */ }
Expand description

DNS resolver service.

+

Implementations§

source§

impl ResolverService

source

pub fn custom(resolver: impl Resolve + 'static) -> Self

Constructor for custom Resolve trait object and use it as resolver.

+

Trait Implementations§

source§

impl Clone for ResolverService

source§

fn clone(&self) -> ResolverService

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Default for ResolverService

source§

fn default() -> ResolverService

Returns the “default value” for a type. Read more
source§

impl<R: Host> Service<ConnectInfo<R>> for ResolverService

source§

type Response = ConnectInfo<R>

Responses given by the service.
source§

type Error = ConnectError

Errors produced by the service when polling readiness or executing call.
source§

type Future = ResolverFut<R>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: ConnectInfo<R>) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/tcp/index.html b/actix_tls/connect/tcp/index.html new file mode 100644 index 00000000..cf3100f0 --- /dev/null +++ b/actix_tls/connect/tcp/index.html @@ -0,0 +1,3 @@ +actix_tls::connect::tcp - Rust
actix_tls::connect

Module tcp

source
Expand description

TCP connector service.

+

See TcpConnector for main connector service factory docs.

+

Structs§

\ No newline at end of file diff --git a/actix_tls/connect/tcp/sidebar-items.js b/actix_tls/connect/tcp/sidebar-items.js new file mode 100644 index 00000000..845ac971 --- /dev/null +++ b/actix_tls/connect/tcp/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["TcpConnector","TcpConnectorService"]}; \ No newline at end of file diff --git a/actix_tls/connect/tcp/struct.TcpConnector.html b/actix_tls/connect/tcp/struct.TcpConnector.html new file mode 100644 index 00000000..acfa9d03 --- /dev/null +++ b/actix_tls/connect/tcp/struct.TcpConnector.html @@ -0,0 +1,33 @@ +TcpConnector in actix_tls::connect::tcp - Rust
actix_tls::connect::tcp

Struct TcpConnector

source
#[non_exhaustive]
pub struct TcpConnector;
Expand description

TCP connector service factory.

+

Implementations§

source§

impl TcpConnector

source

pub fn service(&self) -> TcpConnectorService

Returns a new TCP connector service.

+

Trait Implementations§

source§

impl Clone for TcpConnector

source§

fn clone(&self) -> TcpConnector

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for TcpConnector

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for TcpConnector

source§

fn default() -> TcpConnector

Returns the “default value” for a type. Read more
source§

impl<R: Host> ServiceFactory<ConnectInfo<R>> for TcpConnector

source§

type Response = Connection<R, TcpStream>

Responses given by the created services.
source§

type Error = ConnectError

Errors produced by the created services.
source§

type Config = ()

Service factory configuration.
source§

type Service = TcpConnectorService

The kind of Service created by this factory.
source§

type InitError = ()

Errors potentially raised while building a service.
source§

type Future = Ready<Result<<TcpConnector as ServiceFactory<ConnectInfo<R>>>::Service, <TcpConnector as ServiceFactory<ConnectInfo<R>>>::InitError>>

The future of the Service instance.g
source§

fn new_service(&self, _: ()) -> Self::Future

Create and return a new service asynchronously.
source§

impl Copy for TcpConnector

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<SF, Req> IntoServiceFactory<SF, Req> for SF
where + SF: ServiceFactory<Req>,

§

fn into_factory(self) -> SF

Convert Self to a ServiceFactory
§

impl<SF, Req> ServiceFactoryExt<Req> for SF
where + SF: ServiceFactory<Req>,

§

fn map<F, R>(self, f: F) -> MapServiceFactory<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R + Clone,

Map this service’s output to a different type, returning a new service +of the resulting type.
§

fn map_err<F, E>(self, f: F) -> MapErrServiceFactory<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E + Clone,

Map this service’s error to a different error, returning a new service.
§

fn map_init_err<F, E>(self, f: F) -> MapInitErr<Self, F, Req, E>
where + Self: Sized, + F: Fn(Self::InitError) -> E + Clone,

Map this factory’s init error to a different error, returning a new service.
§

fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
where + Self: Sized, + Self::Config: Clone, + I: IntoServiceFactory<SF1, Self::Response>, + SF1: ServiceFactory<Self::Response, Config = Self::Config, Error = Self::Error, InitError = Self::InitError>,

Call another service after call to this one has resolved successfully.
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/tcp/struct.TcpConnectorService.html b/actix_tls/connect/tcp/struct.TcpConnectorService.html new file mode 100644 index 00000000..83f992e0 --- /dev/null +++ b/actix_tls/connect/tcp/struct.TcpConnectorService.html @@ -0,0 +1,29 @@ +TcpConnectorService in actix_tls::connect::tcp - Rust
actix_tls::connect::tcp

Struct TcpConnectorService

source
#[non_exhaustive]
pub struct TcpConnectorService;
Expand description

TCP connector service.

+

Trait Implementations§

source§

impl Clone for TcpConnectorService

source§

fn clone(&self) -> TcpConnectorService

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for TcpConnectorService

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for TcpConnectorService

source§

fn default() -> TcpConnectorService

Returns the “default value” for a type. Read more
source§

impl<R: Host> Service<ConnectInfo<R>> for TcpConnectorService

source§

type Response = Connection<R, TcpStream>

Responses given by the service.
source§

type Error = ConnectError

Errors produced by the service when polling readiness or executing call.
source§

type Future = TcpConnectorFut<R>

The future response value.
source§

fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: ConnectInfo<R>) -> Self::Future

Process the request and return the response asynchronously. Read more
source§

impl Copy for TcpConnectorService

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tls/connect/trait.Host.html b/actix_tls/connect/trait.Host.html new file mode 100644 index 00000000..af8d95ba --- /dev/null +++ b/actix_tls/connect/trait.Host.html @@ -0,0 +1,17 @@ +Host in actix_tls::connect - Rust
actix_tls::connect

Trait Host

source
pub trait Host: Unpin + 'static {
+    // Required method
+    fn hostname(&self) -> &str;
+
+    // Provided method
+    fn port(&self) -> Option<u16> { ... }
+}
Expand description

An interface for types where host parts (hostname and port) can be derived.

+

The WHATWG URL Standard defines the terminology used for this trait and its methods.

+
+------------------------+
+|          host          |
++-----------------+------+
+|    hostname     | port |
+|                 |      |
+| sub.example.com : 8080 |
++-----------------+------+

Required Methods§

source

fn hostname(&self) -> &str

Extract hostname.

+

Provided Methods§

source

fn port(&self) -> Option<u16>

Extract optional port.

+

Implementations on Foreign Types§

source§

impl Host for &'static str

source§

fn hostname(&self) -> &str

source§

fn port(&self) -> Option<u16>

source§

impl Host for String

source§

fn hostname(&self) -> &str

source§

fn port(&self) -> Option<u16>

source§

impl Host for Uri

source§

fn hostname(&self) -> &str

source§

fn port(&self) -> Option<u16>

source§

impl Host for Uri

source§

fn hostname(&self) -> &str

source§

fn port(&self) -> Option<u16>

Implementors§

\ No newline at end of file diff --git a/actix_tls/connect/trait.Resolve.html b/actix_tls/connect/trait.Resolve.html new file mode 100644 index 00000000..60cce6da --- /dev/null +++ b/actix_tls/connect/trait.Resolve.html @@ -0,0 +1,58 @@ +Resolve in actix_tls::connect - Rust
actix_tls::connect

Trait Resolve

source
pub trait Resolve {
+    // Required method
+    fn lookup<'a>(
+        &'a self,
+        host: &'a str,
+        port: u16,
+    ) -> LocalBoxFuture<'a, Result<Vec<SocketAddr>, Box<dyn StdError>>>;
+}
Expand description

Custom async DNS resolvers.

+

§Examples

+
use std::net::SocketAddr;
+
+use actix_tls::connect::{Resolve, Resolver};
+use futures_util::future::LocalBoxFuture;
+
+// use trust-dns async tokio resolver
+use trust_dns_resolver::TokioAsyncResolver;
+
+struct MyResolver {
+    trust_dns: TokioAsyncResolver,
+};
+
+// impl Resolve trait and convert given host address str and port to SocketAddr.
+impl Resolve for MyResolver {
+    fn lookup<'a>(
+        &'a self,
+        host: &'a str,
+        port: u16,
+    ) -> LocalBoxFuture<'a, Result<Vec<SocketAddr>, Box<dyn std::error::Error>>> {
+        Box::pin(async move {
+            let res = self
+                .trust_dns
+                .lookup_ip(host)
+                .await?
+                .iter()
+                .map(|ip| SocketAddr::new(ip, port))
+                .collect();
+            Ok(res)
+        })
+    }
+}
+
+let my_resolver = MyResolver {
+    trust_dns: TokioAsyncResolver::tokio_from_system_conf().unwrap(),
+};
+
+// wrap custom resolver
+let resolver = Resolver::custom(my_resolver);
+
+// resolver can be passed to connector factory where returned service factory
+// can be used to construct new connector services for use in clients
+let factory = actix_tls::connect::Connector::new(resolver);
+let connector = factory.service();
+

Required Methods§

source

fn lookup<'a>( + &'a self, + host: &'a str, + port: u16, +) -> LocalBoxFuture<'a, Result<Vec<SocketAddr>, Box<dyn StdError>>>

Given DNS lookup information, returns a future that completes with socket information.

+

Implementors§

\ No newline at end of file diff --git a/actix_tls/index.html b/actix_tls/index.html new file mode 100644 index 00000000..f0de37b2 --- /dev/null +++ b/actix_tls/index.html @@ -0,0 +1,2 @@ +actix_tls - Rust

Crate actix_tls

source
Expand description

TLS acceptor and connector services for the Actix ecosystem.

+

Modules§

  • TLS connection acceptor services.
  • TCP and TLS connector services.
\ No newline at end of file diff --git a/actix_tls/sidebar-items.js b/actix_tls/sidebar-items.js new file mode 100644 index 00000000..d1b2efad --- /dev/null +++ b/actix_tls/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["accept","connect"]}; \ No newline at end of file diff --git a/actix_tracing/all.html b/actix_tracing/all.html new file mode 100644 index 00000000..e13f7a54 --- /dev/null +++ b/actix_tracing/all.html @@ -0,0 +1 @@ +List of all items in this crate

List of all items

Structs

Functions

\ No newline at end of file diff --git a/actix_tracing/fn.trace.html b/actix_tracing/fn.trace.html new file mode 100644 index 00000000..e704b435 --- /dev/null +++ b/actix_tracing/fn.trace.html @@ -0,0 +1,17 @@ +trace in actix_tracing - Rust
actix_tracing

Function trace

source
pub fn trace<S, Req, I, F>(
+    service_factory: I,
+    make_span: F,
+) -> ApplyTransform<TracingTransform<S::Service, S, F>, S, Req>
where + I: IntoServiceFactory<S, Req>, + S: ServiceFactory<Req>, + F: Fn(&Req) -> Option<Span> + Clone,
Expand description

Wraps the provided service factory with a transform that automatically +enters/exits the given span.

+

The span to be entered/exited can be provided via a closure. The closure +is passed in a reference to the request being handled by the service.

+

For example:

+ +
let traced_service = trace(
+    web_service,
+    |req: &Request| Some(span!(Level::INFO, "request", req.id))
+);
+
\ No newline at end of file diff --git a/actix_tracing/index.html b/actix_tracing/index.html new file mode 100644 index 00000000..7f42edb4 --- /dev/null +++ b/actix_tracing/index.html @@ -0,0 +1,4 @@ +actix_tracing - Rust

Crate actix_tracing

source
Expand description

Actix tracing - support for tokio tracing with Actix services.

+

Structs§

Functions§

  • Wraps the provided service factory with a transform that automatically +enters/exits the given span.
\ No newline at end of file diff --git a/actix_tracing/sidebar-items.js b/actix_tracing/sidebar-items.js new file mode 100644 index 00000000..e9c74c73 --- /dev/null +++ b/actix_tracing/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["trace"],"struct":["TracingService","TracingTransform"]}; \ No newline at end of file diff --git a/actix_tracing/struct.TracingService.html b/actix_tracing/struct.TracingService.html new file mode 100644 index 00000000..afe1a59a --- /dev/null +++ b/actix_tracing/struct.TracingService.html @@ -0,0 +1,49 @@ +TracingService in actix_tracing - Rust
actix_tracing

Struct TracingService

source
pub struct TracingService<S, F> { /* private fields */ }
Expand description

A Service implementation that automatically enters/exits tracing spans +for the wrapped inner service.

+

Implementations§

source§

impl<S, F> TracingService<S, F>

source

pub fn new(inner: S, make_span: F) -> Self

Trait Implementations§

source§

impl<S: Clone, F: Clone> Clone for TracingService<S, F>

source§

fn clone(&self) -> TracingService<S, F>

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<S, Req, F> Service<Req> for TracingService<S, F>
where + S: Service<Req>, + F: Fn(&Req) -> Option<Span>,

source§

type Response = <S as Service<Req>>::Response

Responses given by the service.
source§

type Error = <S as Service<Req>>::Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = Either<<S as Service<Req>>::Future, Instrumented<<S as Service<Req>>::Future>>

The future response value.
source§

fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, req: Req) -> Self::Future

Process the request and return the response asynchronously. Read more

Auto Trait Implementations§

§

impl<S, F> Freeze for TracingService<S, F>
where + S: Freeze, + F: Freeze,

§

impl<S, F> RefUnwindSafe for TracingService<S, F>
where + S: RefUnwindSafe, + F: RefUnwindSafe,

§

impl<S, F> Send for TracingService<S, F>
where + S: Send, + F: Send,

§

impl<S, F> Sync for TracingService<S, F>
where + S: Sync, + F: Sync,

§

impl<S, F> Unpin for TracingService<S, F>
where + S: Unpin, + F: Unpin,

§

impl<S, F> UnwindSafe for TracingService<S, F>
where + S: UnwindSafe, + F: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an +Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
§

impl<S, Req> IntoService<S, Req> for S
where + S: Service<Req>,

§

fn into_service(self) -> S

Convert to a Service
§

impl<S, Req> ServiceExt<Req> for S
where + S: Service<Req>,

§

fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
where + Self: Sized, + F: FnMut(Self::Response) -> R,

Map this service’s output to a different type, returning a new service +of the resulting type. Read more
§

fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
where + Self: Sized, + F: Fn(Self::Error) -> E,

Map this service’s error to a different error, returning a new service. Read more
§

fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
where + Self: Sized, + I: IntoService<S1, Self::Response>, + S1: Service<Self::Response, Error = Self::Error>,

Call another service after call to this one has resolved successfully. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +WithDispatch wrapper. Read more
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_tracing/struct.TracingTransform.html b/actix_tracing/struct.TracingTransform.html new file mode 100644 index 00000000..536db88d --- /dev/null +++ b/actix_tracing/struct.TracingTransform.html @@ -0,0 +1,31 @@ +TracingTransform in actix_tracing - Rust
actix_tracing

Struct TracingTransform

source
pub struct TracingTransform<S, U, F> { /* private fields */ }
Expand description

A Transform implementation that wraps services with a TracingService.

+

Implementations§

source§

impl<S, U, F> TracingTransform<S, U, F>

source

pub fn new(make_span: F) -> Self

Trait Implementations§

source§

impl<S, Req, U, F> Transform<S, Req> for TracingTransform<S, U, F>
where + S: Service<Req>, + U: ServiceFactory<Req, Response = S::Response, Error = S::Error, Service = S>, + F: Fn(&Req) -> Option<Span> + Clone,

source§

type Response = <S as Service<Req>>::Response

Responses produced by the service.
source§

type Error = <S as Service<Req>>::Error

Errors produced by the service.
source§

type Transform = TracingService<S, F>

The TransformService value created by this factory
source§

type InitError = <U as ServiceFactory<Req>>::InitError

Errors produced while building a transform service.
source§

type Future = Ready<Result<<TracingTransform<S, U, F> as Transform<S, Req>>::Transform, <TracingTransform<S, U, F> as Transform<S, Req>>::InitError>>

The future response value.
source§

fn new_transform(&self, service: S) -> Self::Future

Creates and returns a new Transform component, asynchronously

Auto Trait Implementations§

§

impl<S, U, F> Freeze for TracingTransform<S, U, F>
where + F: Freeze,

§

impl<S, U, F> RefUnwindSafe for TracingTransform<S, U, F>
where + F: RefUnwindSafe,

§

impl<S, U, F> Send for TracingTransform<S, U, F>
where + F: Send,

§

impl<S, U, F> Sync for TracingTransform<S, U, F>
where + F: Sync,

§

impl<S, U, F> Unpin for TracingTransform<S, U, F>
where + F: Unpin,

§

impl<S, U, F> UnwindSafe for TracingTransform<S, U, F>
where + F: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an +Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an +Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +WithDispatch wrapper. Read more
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a +[WithDispatch] wrapper. Read more
\ No newline at end of file diff --git a/actix_utils/all.html b/actix_utils/all.html new file mode 100644 index 00000000..1707a5a2 --- /dev/null +++ b/actix_utils/all.html @@ -0,0 +1 @@ +List of all items in this crate
\ No newline at end of file diff --git a/actix_utils/counter/index.html b/actix_utils/counter/index.html new file mode 100644 index 00000000..0b5164e9 --- /dev/null +++ b/actix_utils/counter/index.html @@ -0,0 +1,2 @@ +actix_utils::counter - Rust
actix_utils

Module counter

source
Expand description

Task-notifying counter.

+

Structs§

  • Simple counter with ability to notify task on reaching specific number
  • An RAII structure that keeps the underlying counter incremented until this guard is dropped.
\ No newline at end of file diff --git a/actix_utils/counter/sidebar-items.js b/actix_utils/counter/sidebar-items.js new file mode 100644 index 00000000..1d8e4e9f --- /dev/null +++ b/actix_utils/counter/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["Counter","CounterGuard"]}; \ No newline at end of file diff --git a/actix_utils/counter/struct.Counter.html b/actix_utils/counter/struct.Counter.html new file mode 100644 index 00000000..e8e7bd3a --- /dev/null +++ b/actix_utils/counter/struct.Counter.html @@ -0,0 +1,19 @@ +Counter in actix_utils::counter - Rust
actix_utils::counter

Struct Counter

source
pub struct Counter(/* private fields */);
Expand description

Simple counter with ability to notify task on reaching specific number

+

Counter could be cloned, total n-count is shared across all clones.

+

Implementations§

source§

impl Counter

source

pub fn new(capacity: usize) -> Self

Create Counter instance with max value.

+
source

pub fn get(&self) -> CounterGuard

Create new counter guard, incrementing the counter.

+
source

pub fn available(&self, cx: &Context<'_>) -> bool

Returns true if counter is below capacity. Otherwise, register to wake task when it is.

+
source

pub fn total(&self) -> usize

Get total number of acquired guards.

+

Trait Implementations§

source§

impl Clone for Counter

source§

fn clone(&self) -> Counter

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Counter

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Counter

§

impl !RefUnwindSafe for Counter

§

impl !Send for Counter

§

impl !Sync for Counter

§

impl Unpin for Counter

§

impl !UnwindSafe for Counter

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_utils/counter/struct.CounterGuard.html b/actix_utils/counter/struct.CounterGuard.html new file mode 100644 index 00000000..08a8528d --- /dev/null +++ b/actix_utils/counter/struct.CounterGuard.html @@ -0,0 +1,12 @@ +CounterGuard in actix_utils::counter - Rust
actix_utils::counter

Struct CounterGuard

source
pub struct CounterGuard(/* private fields */);
Expand description

An RAII structure that keeps the underlying counter incremented until this guard is dropped.

+

Trait Implementations§

source§

impl Debug for CounterGuard

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Drop for CounterGuard

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl Unpin for CounterGuard

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_utils/future/either/enum.Either.html b/actix_utils/future/either/enum.Either.html new file mode 100644 index 00000000..7d566b61 --- /dev/null +++ b/actix_utils/future/either/enum.Either.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_utils/future/enum.Either.html...

+ + + \ No newline at end of file diff --git a/actix_utils/future/enum.Either.html b/actix_utils/future/enum.Either.html new file mode 100644 index 00000000..9c047706 --- /dev/null +++ b/actix_utils/future/enum.Either.html @@ -0,0 +1,50 @@ +Either in actix_utils::future - Rust
actix_utils::future

Enum Either

source
pub enum Either<L, R> {
+    Left {
+        value: L,
+    },
+    Right {
+        value: R,
+    },
+}
Expand description

Combines two different futures that have the same output type.

+

Construct variants with Either::left and Either::right.

+

§Examples

+
use actix_utils::future::{ready, Ready, Either};
+
+let res = Either::<_, Ready<usize>>::left(ready(42));
+assert_eq!(res.await, 42);
+
+let res = Either::<Ready<usize>, _>::right(ready(43));
+assert_eq!(res.await, 43);
+

Variants§

§

Left

A value of type L.

+

Fields

§value: L
§

Right

A value of type R.

+

Fields

§value: R

Implementations§

source§

impl<L, R> Either<L, R>

source

pub fn left(value: L) -> Either<L, R>

Creates new Either using left variant.

+
source

pub fn right(value: R) -> Either<L, R>

Creates new Either using right variant.

+
source§

impl<T> Either<T, T>

source

pub fn into_inner(self) -> T

Unwraps into inner value when left and right have a common type.

+

Trait Implementations§

source§

impl<L: Clone, R: Clone> Clone for Either<L, R>

source§

fn clone(&self) -> Either<L, R>

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<L: Debug, R: Debug> Debug for Either<L, R>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<L, R> Future for Either<L, R>
where + L: Future, + R: Future<Output = L::Output>,

source§

type Output = <L as Future>::Output

The type of value produced on completion.
source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
source§

impl<'__pin, L, R> Unpin for Either<L, R>
where + __Origin<'__pin, L, R>: Unpin,

Auto Trait Implementations§

§

impl<L, R> Freeze for Either<L, R>
where + L: Freeze, + R: Freeze,

§

impl<L, R> RefUnwindSafe for Either<L, R>
where + L: RefUnwindSafe, + R: RefUnwindSafe,

§

impl<L, R> Send for Either<L, R>
where + L: Send, + R: Send,

§

impl<L, R> Sync for Either<L, R>
where + L: Sync, + R: Sync,

§

impl<L, R> UnwindSafe for Either<L, R>
where + L: UnwindSafe, + R: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<F> IntoFuture for F
where + F: Future,

source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
source§

type IntoFuture = F

Which kind of future are we turning this into?
source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_utils/future/fn.err.html b/actix_utils/future/fn.err.html new file mode 100644 index 00000000..e5e99d6b --- /dev/null +++ b/actix_utils/future/fn.err.html @@ -0,0 +1,7 @@ +err in actix_utils::future - Rust
actix_utils::future

Function err

source
pub fn err<T, E>(err: E) -> Ready<Result<T, E>> 
Expand description

Creates a future that is immediately ready with an error value.

+

§Examples

+
use actix_utils::future::err;
+
+let a = err::<(), _>(1);
+assert_eq!(a.await, Err(1));
+
\ No newline at end of file diff --git a/actix_utils/future/fn.ok.html b/actix_utils/future/fn.ok.html new file mode 100644 index 00000000..a3bc1482 --- /dev/null +++ b/actix_utils/future/fn.ok.html @@ -0,0 +1,7 @@ +ok in actix_utils::future - Rust
actix_utils::future

Function ok

source
pub fn ok<T, E>(val: T) -> Ready<Result<T, E>> 
Expand description

Creates a future that is immediately ready with a success value.

+

§Examples

+
use actix_utils::future::ok;
+
+let a = ok::<_, ()>(1);
+assert_eq!(a.await, Ok(1));
+
\ No newline at end of file diff --git a/actix_utils/future/fn.poll_fn.html b/actix_utils/future/fn.poll_fn.html new file mode 100644 index 00000000..0c3aead6 --- /dev/null +++ b/actix_utils/future/fn.poll_fn.html @@ -0,0 +1,20 @@ +poll_fn in actix_utils::future - Rust
actix_utils::future

Function poll_fn

source
pub fn poll_fn<F, T>(f: F) -> PollFn<F> 
where + F: FnMut(&mut Context<'_>) -> Poll<T>,
Expand description

Creates a future driven by the provided function that receives a task context.

+

§Examples

+
let res = poll_fn(|_| Poll::Ready(42)).await;
+assert_eq!(res, 42);
+
+let mut i = 5;
+let res = poll_fn(|cx| {
+    i -= 1;
+
+    if i > 0 {
+        cx.waker().wake_by_ref();
+        Poll::Pending
+    } else {
+        Poll::Ready(42)
+    }
+})
+.await;
+assert_eq!(res, 42);
+
\ No newline at end of file diff --git a/actix_utils/future/fn.ready.html b/actix_utils/future/fn.ready.html new file mode 100644 index 00000000..2807c4cf --- /dev/null +++ b/actix_utils/future/fn.ready.html @@ -0,0 +1,11 @@ +ready in actix_utils::future - Rust
actix_utils::future

Function ready

source
pub fn ready<T>(val: T) -> Ready<T> 
Expand description

Creates a future that is immediately ready with a value.

+

§Examples

+
use actix_utils::future::ready;
+
+let a = ready(1);
+assert_eq!(a.await, 1);
+
+// sync
+let a = ready(1);
+assert_eq!(a.into_inner(), 1);
+
\ No newline at end of file diff --git a/actix_utils/future/index.html b/actix_utils/future/index.html new file mode 100644 index 00000000..0c5b99a2 --- /dev/null +++ b/actix_utils/future/index.html @@ -0,0 +1,2 @@ +actix_utils::future - Rust
actix_utils

Module future

source
Expand description

Helpers for constructing futures.

+

Structs§

Enums§

  • Combines two different futures that have the same output type.

Functions§

  • Creates a future that is immediately ready with an error value.
  • Creates a future that is immediately ready with a success value.
  • Creates a future driven by the provided function that receives a task context.
  • Creates a future that is immediately ready with a value.
\ No newline at end of file diff --git a/actix_utils/future/poll_fn/fn.poll_fn.html b/actix_utils/future/poll_fn/fn.poll_fn.html new file mode 100644 index 00000000..237fed57 --- /dev/null +++ b/actix_utils/future/poll_fn/fn.poll_fn.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_utils/future/fn.poll_fn.html...

+ + + \ No newline at end of file diff --git a/actix_utils/future/poll_fn/struct.PollFn.html b/actix_utils/future/poll_fn/struct.PollFn.html new file mode 100644 index 00000000..04123051 --- /dev/null +++ b/actix_utils/future/poll_fn/struct.PollFn.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_utils/future/struct.PollFn.html...

+ + + \ No newline at end of file diff --git a/actix_utils/future/ready/fn.err.html b/actix_utils/future/ready/fn.err.html new file mode 100644 index 00000000..0a788ef2 --- /dev/null +++ b/actix_utils/future/ready/fn.err.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_utils/future/fn.err.html...

+ + + \ No newline at end of file diff --git a/actix_utils/future/ready/fn.ok.html b/actix_utils/future/ready/fn.ok.html new file mode 100644 index 00000000..fa6909c7 --- /dev/null +++ b/actix_utils/future/ready/fn.ok.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_utils/future/fn.ok.html...

+ + + \ No newline at end of file diff --git a/actix_utils/future/ready/fn.ready.html b/actix_utils/future/ready/fn.ready.html new file mode 100644 index 00000000..1d4d8e94 --- /dev/null +++ b/actix_utils/future/ready/fn.ready.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_utils/future/fn.ready.html...

+ + + \ No newline at end of file diff --git a/actix_utils/future/ready/struct.Ready.html b/actix_utils/future/ready/struct.Ready.html new file mode 100644 index 00000000..05abbb02 --- /dev/null +++ b/actix_utils/future/ready/struct.Ready.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../actix_utils/future/struct.Ready.html...

+ + + \ No newline at end of file diff --git a/actix_utils/future/sidebar-items.js b/actix_utils/future/sidebar-items.js new file mode 100644 index 00000000..7c524289 --- /dev/null +++ b/actix_utils/future/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":["Either"],"fn":["err","ok","poll_fn","ready"],"struct":["PollFn","Ready"]}; \ No newline at end of file diff --git a/actix_utils/future/struct.PollFn.html b/actix_utils/future/struct.PollFn.html new file mode 100644 index 00000000..9ee0f6ee --- /dev/null +++ b/actix_utils/future/struct.PollFn.html @@ -0,0 +1,21 @@ +PollFn in actix_utils::future - Rust
actix_utils::future

Struct PollFn

source
pub struct PollFn<F> { /* private fields */ }
Expand description

Future for the poll_fn function.

+

Trait Implementations§

source§

impl<F> Debug for PollFn<F>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<F, T> Future for PollFn<F>
where + F: FnMut(&mut Context<'_>) -> Poll<T>,

source§

type Output = T

The type of value produced on completion.
source§

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations§

§

impl<F> Freeze for PollFn<F>
where + F: Freeze,

§

impl<F> RefUnwindSafe for PollFn<F>
where + F: RefUnwindSafe,

§

impl<F> Send for PollFn<F>
where + F: Send,

§

impl<F> Sync for PollFn<F>
where + F: Sync,

§

impl<F> Unpin for PollFn<F>
where + F: Unpin,

§

impl<F> UnwindSafe for PollFn<F>
where + F: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<F> IntoFuture for F
where + F: Future,

source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
source§

type IntoFuture = F

Which kind of future are we turning this into?
source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_utils/future/struct.Ready.html b/actix_utils/future/struct.Ready.html new file mode 100644 index 00000000..2154d382 --- /dev/null +++ b/actix_utils/future/struct.Ready.html @@ -0,0 +1,33 @@ +Ready in actix_utils::future - Rust
actix_utils::future

Struct Ready

source
pub struct Ready<T> { /* private fields */ }
Expand description

Future for the ready function.

+

Panic will occur if polled more than once.

+

§Examples

+
use actix_utils::future::ready;
+
+// async
+let a = ready(1);
+assert_eq!(a.await, 1);
+
+// sync
+let a = ready(1);
+assert_eq!(a.into_inner(), 1);
+

Implementations§

source§

impl<T> Ready<T>

source

pub fn into_inner(self) -> T

Unwraps the value from this immediately ready future.

+

Trait Implementations§

source§

impl<T: Clone> Clone for Ready<T>

source§

fn clone(&self) -> Ready<T>

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug> Debug for Ready<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T> Future for Ready<T>

source§

type Output = T

The type of value produced on completion.
source§

fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T>

Attempts to resolve the future to a final value, registering +the current task for wakeup if the value is not yet available. Read more
source§

impl<T> Unpin for Ready<T>

Auto Trait Implementations§

§

impl<T> Freeze for Ready<T>
where + T: Freeze,

§

impl<T> RefUnwindSafe for Ready<T>
where + T: RefUnwindSafe,

§

impl<T> Send for Ready<T>
where + T: Send,

§

impl<T> Sync for Ready<T>
where + T: Sync,

§

impl<T> UnwindSafe for Ready<T>
where + T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<F> IntoFuture for F
where + F: Future,

source§

type Output = <F as Future>::Output

The output that the future will produce on completion.
source§

type IntoFuture = F

Which kind of future are we turning this into?
source§

fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/actix_utils/index.html b/actix_utils/index.html new file mode 100644 index 00000000..152ea941 --- /dev/null +++ b/actix_utils/index.html @@ -0,0 +1,2 @@ +actix_utils - Rust

Crate actix_utils

source
Expand description

Various utilities used in the Actix ecosystem.

+

Modules§

  • Task-notifying counter.
  • Helpers for constructing futures.
\ No newline at end of file diff --git a/actix_utils/sidebar-items.js b/actix_utils/sidebar-items.js new file mode 100644 index 00000000..f6a4148c --- /dev/null +++ b/actix_utils/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["counter","future"]}; \ No newline at end of file diff --git a/bytestring/all.html b/bytestring/all.html new file mode 100644 index 00000000..8566ec23 --- /dev/null +++ b/bytestring/all.html @@ -0,0 +1 @@ +List of all items in this crate

List of all items

Structs

\ No newline at end of file diff --git a/bytestring/index.html b/bytestring/index.html new file mode 100644 index 00000000..64d9a408 --- /dev/null +++ b/bytestring/index.html @@ -0,0 +1,3 @@ +bytestring - Rust

Crate bytestring

source
Expand description

A UTF-8 encoded read-only string using Bytes as storage.

+

See docs for ByteString.

+

Structs§

  • An immutable UTF-8 encoded string with [Bytes] as a storage.
\ No newline at end of file diff --git a/bytestring/sidebar-items.js b/bytestring/sidebar-items.js new file mode 100644 index 00000000..6cfaf287 --- /dev/null +++ b/bytestring/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["ByteString"]}; \ No newline at end of file diff --git a/bytestring/struct.ByteString.html b/bytestring/struct.ByteString.html new file mode 100644 index 00000000..3aebfe63 --- /dev/null +++ b/bytestring/struct.ByteString.html @@ -0,0 +1,1302 @@ +ByteString in bytestring - Rust
bytestring

Struct ByteString

source
pub struct ByteString(/* private fields */);
Expand description

An immutable UTF-8 encoded string with [Bytes] as a storage.

+

Implementations§

source§

impl ByteString

source

pub const fn new() -> Self

Creates a new empty ByteString.

+
source

pub fn as_bytes(&self) -> &Bytes

Get a reference to the underlying Bytes object.

+
source

pub fn into_bytes(self) -> Bytes

Unwraps this ByteString into the underlying Bytes object.

+
source

pub const fn from_static(src: &'static str) -> ByteString

Creates a new ByteString from a &'static str.

+
source

pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString

Creates a new ByteString from a Bytes.

+
§Safety
+

This function is unsafe because it does not check the bytes passed to it are valid UTF-8. +If this constraint is violated, it may cause memory unsafety issues with future users of +the ByteString, as we assume that ByteStrings are valid UTF-8. However, the most likely +issue is that the data gets corrupted.

+
source

pub fn slice_ref(&self, subset: &str) -> Self

Returns a new byte string that is equivalent to the given subset.

+

When processing a ByteString buffer with other tools, one often gets a &str which is in +fact a slice of the original ByteString; i.e., a subset of it. This function turns that +&str into another ByteString, as if one had sliced the ByteString with the offsets +that correspond to subset.

+

Corresponds to [Bytes::slice_ref].

+

This operation is O(1).

+
§Panics
+

Panics if subset is not a sub-slice of this byte string.

+

Note that strings which are only subsets from an equality perspective do not uphold this +requirement; see examples.

+
§Examples
+
let string = ByteString::from_static(" foo ");
+let subset = string.trim();
+let substring = string.slice_ref(subset);
+assert_eq!(substring, "foo");
+ +
// panics because the given slice is not derived from the original byte string, despite
+// being a logical subset of the string
+ByteString::from_static("foo bar").slice_ref("foo");
+

Methods from Deref<Target = str>§

1.6.0 · source

pub fn len(&self) -> usize

Returns the length of self.

+

This length is in bytes, not chars or graphemes. In other words, +it might not be what a human considers the length of the string.

+
§Examples
+
let len = "foo".len();
+assert_eq!(3, len);
+
+assert_eq!("ƒoo".len(), 4); // fancy f!
+assert_eq!("ƒoo".chars().count(), 3);
+
1.6.0 · source

pub fn is_empty(&self) -> bool

Returns true if self has a length of zero bytes.

+
§Examples
+
let s = "";
+assert!(s.is_empty());
+
+let s = "not empty";
+assert!(!s.is_empty());
+
1.9.0 · source

pub fn is_char_boundary(&self, index: usize) -> bool

Checks that index-th byte is the first byte in a UTF-8 code point +sequence or the end of the string.

+

The start and end of the string (when index == self.len()) are +considered to be boundaries.

+

Returns false if index is greater than self.len().

+
§Examples
+
let s = "Löwe 老虎 Léopard";
+assert!(s.is_char_boundary(0));
+// start of `老`
+assert!(s.is_char_boundary(6));
+assert!(s.is_char_boundary(s.len()));
+
+// second byte of `ö`
+assert!(!s.is_char_boundary(2));
+
+// third byte of `老`
+assert!(!s.is_char_boundary(8));
+
source

pub fn floor_char_boundary(&self, index: usize) -> usize

🔬This is a nightly-only experimental API. (round_char_boundary)

Finds the closest x not exceeding index where is_char_boundary(x) is true.

+

This method can help you truncate a string so that it’s still valid UTF-8, but doesn’t +exceed a given number of bytes. Note that this is done purely at the character level +and can still visually split graphemes, even though the underlying characters aren’t +split. For example, the emoji 🧑‍🔬 (scientist) could be split so that the string only +includes 🧑 (person) instead.

+
§Examples
+
#![feature(round_char_boundary)]
+let s = "❤️🧡💛💚💙💜";
+assert_eq!(s.len(), 26);
+assert!(!s.is_char_boundary(13));
+
+let closest = s.floor_char_boundary(13);
+assert_eq!(closest, 10);
+assert_eq!(&s[..closest], "❤️🧡");
+
source

pub fn ceil_char_boundary(&self, index: usize) -> usize

🔬This is a nightly-only experimental API. (round_char_boundary)

Finds the closest x not below index where is_char_boundary(x) is true.

+

If index is greater than the length of the string, this returns the length of the string.

+

This method is the natural complement to floor_char_boundary. See that method +for more details.

+
§Examples
+
#![feature(round_char_boundary)]
+let s = "❤️🧡💛💚💙💜";
+assert_eq!(s.len(), 26);
+assert!(!s.is_char_boundary(13));
+
+let closest = s.ceil_char_boundary(13);
+assert_eq!(closest, 14);
+assert_eq!(&s[..closest], "❤️🧡💛");
+
1.6.0 · source

pub fn as_bytes(&self) -> &[u8]

Converts a string slice to a byte slice. To convert the byte slice back +into a string slice, use the from_utf8 function.

+
§Examples
+
let bytes = "bors".as_bytes();
+assert_eq!(b"bors", bytes);
+
1.6.0 · source

pub fn as_ptr(&self) -> *const u8

Converts a string slice to a raw pointer.

+

As string slices are a slice of bytes, the raw pointer points to a +u8. This pointer will be pointing to the first byte of the string +slice.

+

The caller must ensure that the returned pointer is never written to. +If you need to mutate the contents of the string slice, use as_mut_ptr.

+
§Examples
+
let s = "Hello";
+let ptr = s.as_ptr();
+
1.20.0 · source

pub fn get<I>(&self, i: I) -> Option<&<I as SliceIndex<str>>::Output>
where + I: SliceIndex<str>,

Returns a subslice of str.

+

This is the non-panicking alternative to indexing the str. Returns +None whenever equivalent indexing operation would panic.

+
§Examples
+
let v = String::from("🗻∈🌏");
+
+assert_eq!(Some("🗻"), v.get(0..4));
+
+// indices not on UTF-8 sequence boundaries
+assert!(v.get(1..).is_none());
+assert!(v.get(..8).is_none());
+
+// out of bounds
+assert!(v.get(..42).is_none());
+
1.20.0 · source

pub unsafe fn get_unchecked<I>(&self, i: I) -> &<I as SliceIndex<str>>::Output
where + I: SliceIndex<str>,

Returns an unchecked subslice of str.

+

This is the unchecked alternative to indexing the str.

+
§Safety
+

Callers of this function are responsible that these preconditions are +satisfied:

+
    +
  • The starting index must not exceed the ending index;
  • +
  • Indexes must be within bounds of the original slice;
  • +
  • Indexes must lie on UTF-8 sequence boundaries.
  • +
+

Failing that, the returned string slice may reference invalid memory or +violate the invariants communicated by the str type.

+
§Examples
+
let v = "🗻∈🌏";
+unsafe {
+    assert_eq!("🗻", v.get_unchecked(0..4));
+    assert_eq!("∈", v.get_unchecked(4..7));
+    assert_eq!("🌏", v.get_unchecked(7..11));
+}
+
1.6.0 · source

pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str

👎Deprecated since 1.29.0: use get_unchecked(begin..end) instead

Creates a string slice from another string slice, bypassing safety +checks.

+

This is generally not recommended, use with caution! For a safe +alternative see str and Index.

+

This new slice goes from begin to end, including begin but +excluding end.

+

To get a mutable string slice instead, see the +slice_mut_unchecked method.

+
§Safety
+

Callers of this function are responsible that three preconditions are +satisfied:

+
    +
  • begin must not exceed end.
  • +
  • begin and end must be byte positions within the string slice.
  • +
  • begin and end must lie on UTF-8 sequence boundaries.
  • +
+
§Examples
+
let s = "Löwe 老虎 Léopard";
+
+unsafe {
+    assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21));
+}
+
+let s = "Hello, world!";
+
+unsafe {
+    assert_eq!("world", s.slice_unchecked(7, 12));
+}
+
1.6.0 · source

pub fn split_at(&self, mid: usize) -> (&str, &str)

Divides one string slice into two at an index.

+

The argument, mid, should be a byte offset from the start of the +string. It must also be on the boundary of a UTF-8 code point.

+

The two slices returned go from the start of the string slice to mid, +and from mid to the end of the string slice.

+

To get mutable string slices instead, see the split_at_mut +method.

+
§Panics
+

Panics if mid is not on a UTF-8 code point boundary, or if it is past +the end of the last code point of the string slice. For a non-panicking +alternative see split_at_checked.

+
§Examples
+
let s = "Per Martin-Löf";
+
+let (first, last) = s.split_at(3);
+
+assert_eq!("Per", first);
+assert_eq!(" Martin-Löf", last);
+
1.80.0 · source

pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)>

Divides one string slice into two at an index.

+

The argument, mid, should be a valid byte offset from the start of the +string. It must also be on the boundary of a UTF-8 code point. The +method returns None if that’s not the case.

+

The two slices returned go from the start of the string slice to mid, +and from mid to the end of the string slice.

+

To get mutable string slices instead, see the split_at_mut_checked +method.

+
§Examples
+
let s = "Per Martin-Löf";
+
+let (first, last) = s.split_at_checked(3).unwrap();
+assert_eq!("Per", first);
+assert_eq!(" Martin-Löf", last);
+
+assert_eq!(None, s.split_at_checked(13));  // Inside “ö”
+assert_eq!(None, s.split_at_checked(16));  // Beyond the string length
+
1.6.0 · source

pub fn chars(&self) -> Chars<'_>

Returns an iterator over the chars of a string slice.

+

As a string slice consists of valid UTF-8, we can iterate through a +string slice by char. This method returns such an iterator.

+

It’s important to remember that char represents a Unicode Scalar +Value, and might not match your idea of what a ‘character’ is. Iteration +over grapheme clusters may be what you actually want. This functionality +is not provided by Rust’s standard library, check crates.io instead.

+
§Examples
+

Basic usage:

+ +
let word = "goodbye";
+
+let count = word.chars().count();
+assert_eq!(7, count);
+
+let mut chars = word.chars();
+
+assert_eq!(Some('g'), chars.next());
+assert_eq!(Some('o'), chars.next());
+assert_eq!(Some('o'), chars.next());
+assert_eq!(Some('d'), chars.next());
+assert_eq!(Some('b'), chars.next());
+assert_eq!(Some('y'), chars.next());
+assert_eq!(Some('e'), chars.next());
+
+assert_eq!(None, chars.next());
+

Remember, chars might not match your intuition about characters:

+ +
let y = "y̆";
+
+let mut chars = y.chars();
+
+assert_eq!(Some('y'), chars.next()); // not 'y̆'
+assert_eq!(Some('\u{0306}'), chars.next());
+
+assert_eq!(None, chars.next());
+
1.6.0 · source

pub fn char_indices(&self) -> CharIndices<'_>

Returns an iterator over the chars of a string slice, and their +positions.

+

As a string slice consists of valid UTF-8, we can iterate through a +string slice by char. This method returns an iterator of both +these chars, as well as their byte positions.

+

The iterator yields tuples. The position is first, the char is +second.

+
§Examples
+

Basic usage:

+ +
let word = "goodbye";
+
+let count = word.char_indices().count();
+assert_eq!(7, count);
+
+let mut char_indices = word.char_indices();
+
+assert_eq!(Some((0, 'g')), char_indices.next());
+assert_eq!(Some((1, 'o')), char_indices.next());
+assert_eq!(Some((2, 'o')), char_indices.next());
+assert_eq!(Some((3, 'd')), char_indices.next());
+assert_eq!(Some((4, 'b')), char_indices.next());
+assert_eq!(Some((5, 'y')), char_indices.next());
+assert_eq!(Some((6, 'e')), char_indices.next());
+
+assert_eq!(None, char_indices.next());
+

Remember, chars might not match your intuition about characters:

+ +
let yes = "y̆es";
+
+let mut char_indices = yes.char_indices();
+
+assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
+assert_eq!(Some((1, '\u{0306}')), char_indices.next());
+
+// note the 3 here - the previous character took up two bytes
+assert_eq!(Some((3, 'e')), char_indices.next());
+assert_eq!(Some((4, 's')), char_indices.next());
+
+assert_eq!(None, char_indices.next());
+
1.6.0 · source

pub fn bytes(&self) -> Bytes<'_>

Returns an iterator over the bytes of a string slice.

+

As a string slice consists of a sequence of bytes, we can iterate +through a string slice by byte. This method returns such an iterator.

+
§Examples
+
let mut bytes = "bors".bytes();
+
+assert_eq!(Some(b'b'), bytes.next());
+assert_eq!(Some(b'o'), bytes.next());
+assert_eq!(Some(b'r'), bytes.next());
+assert_eq!(Some(b's'), bytes.next());
+
+assert_eq!(None, bytes.next());
+
1.6.0 · source

pub fn split_whitespace(&self) -> SplitWhitespace<'_>

Splits a string slice by whitespace.

+

The iterator returned will return string slices that are sub-slices of +the original string slice, separated by any amount of whitespace.

+

‘Whitespace’ is defined according to the terms of the Unicode Derived +Core Property White_Space. If you only want to split on ASCII whitespace +instead, use split_ascii_whitespace.

+
§Examples
+

Basic usage:

+ +
let mut iter = "A few words".split_whitespace();
+
+assert_eq!(Some("A"), iter.next());
+assert_eq!(Some("few"), iter.next());
+assert_eq!(Some("words"), iter.next());
+
+assert_eq!(None, iter.next());
+

All kinds of whitespace are considered:

+ +
let mut iter = " Mary   had\ta\u{2009}little  \n\t lamb".split_whitespace();
+assert_eq!(Some("Mary"), iter.next());
+assert_eq!(Some("had"), iter.next());
+assert_eq!(Some("a"), iter.next());
+assert_eq!(Some("little"), iter.next());
+assert_eq!(Some("lamb"), iter.next());
+
+assert_eq!(None, iter.next());
+

If the string is empty or all whitespace, the iterator yields no string slices:

+ +
assert_eq!("".split_whitespace().next(), None);
+assert_eq!("   ".split_whitespace().next(), None);
+
1.34.0 · source

pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_>

Splits a string slice by ASCII whitespace.

+

The iterator returned will return string slices that are sub-slices of +the original string slice, separated by any amount of ASCII whitespace.

+

To split by Unicode Whitespace instead, use split_whitespace.

+
§Examples
+

Basic usage:

+ +
let mut iter = "A few words".split_ascii_whitespace();
+
+assert_eq!(Some("A"), iter.next());
+assert_eq!(Some("few"), iter.next());
+assert_eq!(Some("words"), iter.next());
+
+assert_eq!(None, iter.next());
+

All kinds of ASCII whitespace are considered:

+ +
let mut iter = " Mary   had\ta little  \n\t lamb".split_ascii_whitespace();
+assert_eq!(Some("Mary"), iter.next());
+assert_eq!(Some("had"), iter.next());
+assert_eq!(Some("a"), iter.next());
+assert_eq!(Some("little"), iter.next());
+assert_eq!(Some("lamb"), iter.next());
+
+assert_eq!(None, iter.next());
+

If the string is empty or all ASCII whitespace, the iterator yields no string slices:

+ +
assert_eq!("".split_ascii_whitespace().next(), None);
+assert_eq!("   ".split_ascii_whitespace().next(), None);
+
1.6.0 · source

pub fn lines(&self) -> Lines<'_>

Returns an iterator over the lines of a string, as string slices.

+

Lines are split at line endings that are either newlines (\n) or +sequences of a carriage return followed by a line feed (\r\n).

+

Line terminators are not included in the lines returned by the iterator.

+

Note that any carriage return (\r) not immediately followed by a +line feed (\n) does not split a line. These carriage returns are +thereby included in the produced lines.

+

The final line ending is optional. A string that ends with a final line +ending will return the same lines as an otherwise identical string +without a final line ending.

+
§Examples
+

Basic usage:

+ +
let text = "foo\r\nbar\n\nbaz\r";
+let mut lines = text.lines();
+
+assert_eq!(Some("foo"), lines.next());
+assert_eq!(Some("bar"), lines.next());
+assert_eq!(Some(""), lines.next());
+// Trailing carriage return is included in the last line
+assert_eq!(Some("baz\r"), lines.next());
+
+assert_eq!(None, lines.next());
+

The final line does not require any ending:

+ +
let text = "foo\nbar\n\r\nbaz";
+let mut lines = text.lines();
+
+assert_eq!(Some("foo"), lines.next());
+assert_eq!(Some("bar"), lines.next());
+assert_eq!(Some(""), lines.next());
+assert_eq!(Some("baz"), lines.next());
+
+assert_eq!(None, lines.next());
+
1.6.0 · source

pub fn lines_any(&self) -> LinesAny<'_>

👎Deprecated since 1.4.0: use lines() instead now

Returns an iterator over the lines of a string.

+
1.8.0 · source

pub fn encode_utf16(&self) -> EncodeUtf16<'_>

Returns an iterator of u16 over the string encoded as UTF-16.

+
§Examples
+
let text = "Zażółć gęślą jaźń";
+
+let utf8_len = text.len();
+let utf16_len = text.encode_utf16().count();
+
+assert!(utf16_len <= utf8_len);
+
1.6.0 · source

pub fn contains<P>(&self, pat: P) -> bool
where + P: Pattern,

Returns true if the given pattern matches a sub-slice of +this string slice.

+

Returns false if it does not.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Examples
+
let bananas = "bananas";
+
+assert!(bananas.contains("nana"));
+assert!(!bananas.contains("apples"));
+
1.6.0 · source

pub fn starts_with<P>(&self, pat: P) -> bool
where + P: Pattern,

Returns true if the given pattern matches a prefix of this +string slice.

+

Returns false if it does not.

+

The pattern can be a &str, in which case this function will return true if +the &str is a prefix of this string slice.

+

The pattern can also be a char, a slice of chars, or a +function or closure that determines if a character matches. +These will only be checked against the first character of this string slice. +Look at the second example below regarding behavior for slices of chars.

+
§Examples
+
let bananas = "bananas";
+
+assert!(bananas.starts_with("bana"));
+assert!(!bananas.starts_with("nana"));
+ +
let bananas = "bananas";
+
+// Note that both of these assert successfully.
+assert!(bananas.starts_with(&['b', 'a', 'n', 'a']));
+assert!(bananas.starts_with(&['a', 'b', 'c', 'd']));
+
1.6.0 · source

pub fn ends_with<P>(&self, pat: P) -> bool
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns true if the given pattern matches a suffix of this +string slice.

+

Returns false if it does not.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Examples
+
let bananas = "bananas";
+
+assert!(bananas.ends_with("anas"));
+assert!(!bananas.ends_with("nana"));
+
1.6.0 · source

pub fn find<P>(&self, pat: P) -> Option<usize>
where + P: Pattern,

Returns the byte index of the first character of this string slice that +matches the pattern.

+

Returns None if the pattern doesn’t match.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Examples
+

Simple patterns:

+ +
let s = "Löwe 老虎 Léopard Gepardi";
+
+assert_eq!(s.find('L'), Some(0));
+assert_eq!(s.find('é'), Some(14));
+assert_eq!(s.find("pard"), Some(17));
+

More complex patterns using point-free style and closures:

+ +
let s = "Löwe 老虎 Léopard";
+
+assert_eq!(s.find(char::is_whitespace), Some(5));
+assert_eq!(s.find(char::is_lowercase), Some(1));
+assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1));
+assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4));
+

Not finding the pattern:

+ +
let s = "Löwe 老虎 Léopard";
+let x: &[_] = &['1', '2'];
+
+assert_eq!(s.find(x), None);
+
1.6.0 · source

pub fn rfind<P>(&self, pat: P) -> Option<usize>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns the byte index for the first character of the last match of the pattern in +this string slice.

+

Returns None if the pattern doesn’t match.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Examples
+

Simple patterns:

+ +
let s = "Löwe 老虎 Léopard Gepardi";
+
+assert_eq!(s.rfind('L'), Some(13));
+assert_eq!(s.rfind('é'), Some(14));
+assert_eq!(s.rfind("pard"), Some(24));
+

More complex patterns with closures:

+ +
let s = "Löwe 老虎 Léopard";
+
+assert_eq!(s.rfind(char::is_whitespace), Some(12));
+assert_eq!(s.rfind(char::is_lowercase), Some(20));
+

Not finding the pattern:

+ +
let s = "Löwe 老虎 Léopard";
+let x: &[_] = &['1', '2'];
+
+assert_eq!(s.rfind(x), None);
+
1.6.0 · source

pub fn split<P>(&self, pat: P) -> Split<'_, P>
where + P: Pattern,

Returns an iterator over substrings of this string slice, separated by +characters matched by a pattern.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator will be a DoubleEndedIterator if the pattern +allows a reverse search and forward/reverse search yields the same +elements. This is true for, e.g., char, but not for &str.

+

If the pattern allows a reverse search but its results might differ +from a forward search, the rsplit method can be used.

+
§Examples
+

Simple patterns:

+ +
let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
+assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
+
+let v: Vec<&str> = "".split('X').collect();
+assert_eq!(v, [""]);
+
+let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
+assert_eq!(v, ["lion", "", "tiger", "leopard"]);
+
+let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
+assert_eq!(v, ["lion", "tiger", "leopard"]);
+
+let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect();
+assert_eq!(v, ["abc", "def", "ghi"]);
+
+let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect();
+assert_eq!(v, ["lion", "tiger", "leopard"]);
+

If the pattern is a slice of chars, split on each occurrence of any of the characters:

+ +
let v: Vec<&str> = "2020-11-03 23:59".split(&['-', ' ', ':', '@'][..]).collect();
+assert_eq!(v, ["2020", "11", "03", "23", "59"]);
+

A more complex pattern, using a closure:

+ +
let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect();
+assert_eq!(v, ["abc", "def", "ghi"]);
+

If a string contains multiple contiguous separators, you will end up +with empty strings in the output:

+ +
let x = "||||a||b|c".to_string();
+let d: Vec<_> = x.split('|').collect();
+
+assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
+

Contiguous separators are separated by the empty string.

+ +
let x = "(///)".to_string();
+let d: Vec<_> = x.split('/').collect();
+
+assert_eq!(d, &["(", "", "", ")"]);
+

Separators at the start or end of a string are neighbored +by empty strings.

+ +
let d: Vec<_> = "010".split("0").collect();
+assert_eq!(d, &["", "1", ""]);
+

When the empty string is used as a separator, it separates +every character in the string, along with the beginning +and end of the string.

+ +
let f: Vec<_> = "rust".split("").collect();
+assert_eq!(f, &["", "r", "u", "s", "t", ""]);
+

Contiguous separators can lead to possibly surprising behavior +when whitespace is used as the separator. This code is correct:

+ +
let x = "    a  b c".to_string();
+let d: Vec<_> = x.split(' ').collect();
+
+assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
+

It does not give you:

+ +
assert_eq!(d, &["a", "b", "c"]);
+

Use split_whitespace for this behavior.

+
1.51.0 · source

pub fn split_inclusive<P>(&self, pat: P) -> SplitInclusive<'_, P>
where + P: Pattern,

Returns an iterator over substrings of this string slice, separated by +characters matched by a pattern.

+

Differs from the iterator produced by split in that split_inclusive +leaves the matched part as the terminator of the substring.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Examples
+
let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb."
+    .split_inclusive('\n').collect();
+assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb."]);
+

If the last element of the string is matched, +that element will be considered the terminator of the preceding substring. +That substring will be the last item returned by the iterator.

+ +
let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb.\n"
+    .split_inclusive('\n').collect();
+assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb.\n"]);
+
1.6.0 · source

pub fn rsplit<P>(&self, pat: P) -> RSplit<'_, P>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns an iterator over substrings of the given string slice, separated +by characters matched by a pattern and yielded in reverse order.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator requires that the pattern supports a reverse +search, and it will be a DoubleEndedIterator if a forward/reverse +search yields the same elements.

+

For iterating from the front, the split method can be used.

+
§Examples
+

Simple patterns:

+ +
let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
+assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
+
+let v: Vec<&str> = "".rsplit('X').collect();
+assert_eq!(v, [""]);
+
+let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect();
+assert_eq!(v, ["leopard", "tiger", "", "lion"]);
+
+let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
+assert_eq!(v, ["leopard", "tiger", "lion"]);
+

A more complex pattern, using a closure:

+ +
let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect();
+assert_eq!(v, ["ghi", "def", "abc"]);
+
1.6.0 · source

pub fn split_terminator<P>(&self, pat: P) -> SplitTerminator<'_, P>
where + P: Pattern,

Returns an iterator over substrings of the given string slice, separated +by characters matched by a pattern.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+

Equivalent to split, except that the trailing substring +is skipped if empty.

+

This method can be used for string data that is terminated, +rather than separated by a pattern.

+
§Iterator behavior
+

The returned iterator will be a DoubleEndedIterator if the pattern +allows a reverse search and forward/reverse search yields the same +elements. This is true for, e.g., char, but not for &str.

+

If the pattern allows a reverse search but its results might differ +from a forward search, the rsplit_terminator method can be used.

+
§Examples
+
let v: Vec<&str> = "A.B.".split_terminator('.').collect();
+assert_eq!(v, ["A", "B"]);
+
+let v: Vec<&str> = "A..B..".split_terminator(".").collect();
+assert_eq!(v, ["A", "", "B", ""]);
+
+let v: Vec<&str> = "A.B:C.D".split_terminator(&['.', ':'][..]).collect();
+assert_eq!(v, ["A", "B", "C", "D"]);
+
1.6.0 · source

pub fn rsplit_terminator<P>(&self, pat: P) -> RSplitTerminator<'_, P>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns an iterator over substrings of self, separated by characters +matched by a pattern and yielded in reverse order.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+

Equivalent to split, except that the trailing substring is +skipped if empty.

+

This method can be used for string data that is terminated, +rather than separated by a pattern.

+
§Iterator behavior
+

The returned iterator requires that the pattern supports a +reverse search, and it will be double ended if a forward/reverse +search yields the same elements.

+

For iterating from the front, the split_terminator method can be +used.

+
§Examples
+
let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect();
+assert_eq!(v, ["B", "A"]);
+
+let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
+assert_eq!(v, ["", "B", "", "A"]);
+
+let v: Vec<&str> = "A.B:C.D".rsplit_terminator(&['.', ':'][..]).collect();
+assert_eq!(v, ["D", "C", "B", "A"]);
+
1.6.0 · source

pub fn splitn<P>(&self, n: usize, pat: P) -> SplitN<'_, P>
where + P: Pattern,

Returns an iterator over substrings of the given string slice, separated +by a pattern, restricted to returning at most n items.

+

If n substrings are returned, the last substring (the nth substring) +will contain the remainder of the string.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator will not be double ended, because it is +not efficient to support.

+

If the pattern allows a reverse search, the rsplitn method can be +used.

+
§Examples
+

Simple patterns:

+ +
let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
+assert_eq!(v, ["Mary", "had", "a little lambda"]);
+
+let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect();
+assert_eq!(v, ["lion", "", "tigerXleopard"]);
+
+let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
+assert_eq!(v, ["abcXdef"]);
+
+let v: Vec<&str> = "".splitn(1, 'X').collect();
+assert_eq!(v, [""]);
+

A more complex pattern, using a closure:

+ +
let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect();
+assert_eq!(v, ["abc", "defXghi"]);
+
1.6.0 · source

pub fn rsplitn<P>(&self, n: usize, pat: P) -> RSplitN<'_, P>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns an iterator over substrings of this string slice, separated by a +pattern, starting from the end of the string, restricted to returning at +most n items.

+

If n substrings are returned, the last substring (the nth substring) +will contain the remainder of the string.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator will not be double ended, because it is not +efficient to support.

+

For splitting from the front, the splitn method can be used.

+
§Examples
+

Simple patterns:

+ +
let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
+assert_eq!(v, ["lamb", "little", "Mary had a"]);
+
+let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect();
+assert_eq!(v, ["leopard", "tiger", "lionX"]);
+
+let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
+assert_eq!(v, ["leopard", "lion::tiger"]);
+

A more complex pattern, using a closure:

+ +
let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect();
+assert_eq!(v, ["ghi", "abc1def"]);
+
1.52.0 · source

pub fn split_once<P>(&self, delimiter: P) -> Option<(&str, &str)>
where + P: Pattern,

Splits the string on the first occurrence of the specified delimiter and +returns prefix before delimiter and suffix after delimiter.

+
§Examples
+
assert_eq!("cfg".split_once('='), None);
+assert_eq!("cfg=".split_once('='), Some(("cfg", "")));
+assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo")));
+assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar")));
+
1.52.0 · source

pub fn rsplit_once<P>(&self, delimiter: P) -> Option<(&str, &str)>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Splits the string on the last occurrence of the specified delimiter and +returns prefix before delimiter and suffix after delimiter.

+
§Examples
+
assert_eq!("cfg".rsplit_once('='), None);
+assert_eq!("cfg=foo".rsplit_once('='), Some(("cfg", "foo")));
+assert_eq!("cfg=foo=bar".rsplit_once('='), Some(("cfg=foo", "bar")));
+
1.6.0 · source

pub fn matches<P>(&self, pat: P) -> Matches<'_, P>
where + P: Pattern,

Returns an iterator over the disjoint matches of a pattern within the +given string slice.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator will be a DoubleEndedIterator if the pattern +allows a reverse search and forward/reverse search yields the same +elements. This is true for, e.g., char, but not for &str.

+

If the pattern allows a reverse search but its results might differ +from a forward search, the rmatches method can be used.

+
§Examples
+
let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
+assert_eq!(v, ["abc", "abc", "abc"]);
+
+let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
+assert_eq!(v, ["1", "2", "3"]);
+
1.6.0 · source

pub fn rmatches<P>(&self, pat: P) -> RMatches<'_, P>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns an iterator over the disjoint matches of a pattern within this +string slice, yielded in reverse order.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator requires that the pattern supports a reverse +search, and it will be a DoubleEndedIterator if a forward/reverse +search yields the same elements.

+

For iterating from the front, the matches method can be used.

+
§Examples
+
let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
+assert_eq!(v, ["abc", "abc", "abc"]);
+
+let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
+assert_eq!(v, ["3", "2", "1"]);
+
1.6.0 · source

pub fn match_indices<P>(&self, pat: P) -> MatchIndices<'_, P>
where + P: Pattern,

Returns an iterator over the disjoint matches of a pattern within this string +slice as well as the index that the match starts at.

+

For matches of pat within self that overlap, only the indices +corresponding to the first match are returned.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator will be a DoubleEndedIterator if the pattern +allows a reverse search and forward/reverse search yields the same +elements. This is true for, e.g., char, but not for &str.

+

If the pattern allows a reverse search but its results might differ +from a forward search, the rmatch_indices method can be used.

+
§Examples
+
let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
+assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
+
+let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
+assert_eq!(v, [(1, "abc"), (4, "abc")]);
+
+let v: Vec<_> = "ababa".match_indices("aba").collect();
+assert_eq!(v, [(0, "aba")]); // only the first `aba`
+
1.6.0 · source

pub fn rmatch_indices<P>(&self, pat: P) -> RMatchIndices<'_, P>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns an iterator over the disjoint matches of a pattern within self, +yielded in reverse order along with the index of the match.

+

For matches of pat within self that overlap, only the indices +corresponding to the last match are returned.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Iterator behavior
+

The returned iterator requires that the pattern supports a reverse +search, and it will be a DoubleEndedIterator if a forward/reverse +search yields the same elements.

+

For iterating from the front, the match_indices method can be used.

+
§Examples
+
let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
+assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
+
+let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
+assert_eq!(v, [(4, "abc"), (1, "abc")]);
+
+let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
+assert_eq!(v, [(2, "aba")]); // only the last `aba`
+
1.6.0 · source

pub fn trim(&self) -> &str

Returns a string slice with leading and trailing whitespace removed.

+

‘Whitespace’ is defined according to the terms of the Unicode Derived +Core Property White_Space, which includes newlines.

+
§Examples
+
let s = "\n Hello\tworld\t\n";
+
+assert_eq!("Hello\tworld", s.trim());
+
1.30.0 · source

pub fn trim_start(&self) -> &str

Returns a string slice with leading whitespace removed.

+

‘Whitespace’ is defined according to the terms of the Unicode Derived +Core Property White_Space, which includes newlines.

+
§Text directionality
+

A string is a sequence of bytes. start in this context means the first +position of that byte string; for a left-to-right language like English or +Russian, this will be left side, and for right-to-left languages like +Arabic or Hebrew, this will be the right side.

+
§Examples
+

Basic usage:

+ +
let s = "\n Hello\tworld\t\n";
+assert_eq!("Hello\tworld\t\n", s.trim_start());
+

Directionality:

+ +
let s = "  English  ";
+assert!(Some('E') == s.trim_start().chars().next());
+
+let s = "  עברית  ";
+assert!(Some('ע') == s.trim_start().chars().next());
+
1.30.0 · source

pub fn trim_end(&self) -> &str

Returns a string slice with trailing whitespace removed.

+

‘Whitespace’ is defined according to the terms of the Unicode Derived +Core Property White_Space, which includes newlines.

+
§Text directionality
+

A string is a sequence of bytes. end in this context means the last +position of that byte string; for a left-to-right language like English or +Russian, this will be right side, and for right-to-left languages like +Arabic or Hebrew, this will be the left side.

+
§Examples
+

Basic usage:

+ +
let s = "\n Hello\tworld\t\n";
+assert_eq!("\n Hello\tworld", s.trim_end());
+

Directionality:

+ +
let s = "  English  ";
+assert!(Some('h') == s.trim_end().chars().rev().next());
+
+let s = "  עברית  ";
+assert!(Some('ת') == s.trim_end().chars().rev().next());
+
1.6.0 · source

pub fn trim_left(&self) -> &str

👎Deprecated since 1.33.0: superseded by trim_start

Returns a string slice with leading whitespace removed.

+

‘Whitespace’ is defined according to the terms of the Unicode Derived +Core Property White_Space.

+
§Text directionality
+

A string is a sequence of bytes. ‘Left’ in this context means the first +position of that byte string; for a language like Arabic or Hebrew +which are ‘right to left’ rather than ‘left to right’, this will be +the right side, not the left.

+
§Examples
+

Basic usage:

+ +
let s = " Hello\tworld\t";
+
+assert_eq!("Hello\tworld\t", s.trim_left());
+

Directionality:

+ +
let s = "  English";
+assert!(Some('E') == s.trim_left().chars().next());
+
+let s = "  עברית";
+assert!(Some('ע') == s.trim_left().chars().next());
+
1.6.0 · source

pub fn trim_right(&self) -> &str

👎Deprecated since 1.33.0: superseded by trim_end

Returns a string slice with trailing whitespace removed.

+

‘Whitespace’ is defined according to the terms of the Unicode Derived +Core Property White_Space.

+
§Text directionality
+

A string is a sequence of bytes. ‘Right’ in this context means the last +position of that byte string; for a language like Arabic or Hebrew +which are ‘right to left’ rather than ‘left to right’, this will be +the left side, not the right.

+
§Examples
+

Basic usage:

+ +
let s = " Hello\tworld\t";
+
+assert_eq!(" Hello\tworld", s.trim_right());
+

Directionality:

+ +
let s = "English  ";
+assert!(Some('h') == s.trim_right().chars().rev().next());
+
+let s = "עברית  ";
+assert!(Some('ת') == s.trim_right().chars().rev().next());
+
1.6.0 · source

pub fn trim_matches<P>(&self, pat: P) -> &str
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> DoubleEndedSearcher<'a>,

Returns a string slice with all prefixes and suffixes that match a +pattern repeatedly removed.

+

The pattern can be a char, a slice of chars, or a function +or closure that determines if a character matches.

+
§Examples
+

Simple patterns:

+ +
assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
+assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar");
+
+let x: &[_] = &['1', '2'];
+assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
+

A more complex pattern, using a closure:

+ +
assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
+
1.30.0 · source

pub fn trim_start_matches<P>(&self, pat: P) -> &str
where + P: Pattern,

Returns a string slice with all prefixes that match a pattern +repeatedly removed.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Text directionality
+

A string is a sequence of bytes. start in this context means the first +position of that byte string; for a left-to-right language like English or +Russian, this will be left side, and for right-to-left languages like +Arabic or Hebrew, this will be the right side.

+
§Examples
+
assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
+assert_eq!("123foo1bar123".trim_start_matches(char::is_numeric), "foo1bar123");
+
+let x: &[_] = &['1', '2'];
+assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12");
+
1.45.0 · source

pub fn strip_prefix<P>(&self, prefix: P) -> Option<&str>
where + P: Pattern,

Returns a string slice with the prefix removed.

+

If the string starts with the pattern prefix, returns the substring after the prefix, +wrapped in Some. Unlike trim_start_matches, this method removes the prefix exactly once.

+

If the string does not start with prefix, returns None.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Examples
+
assert_eq!("foo:bar".strip_prefix("foo:"), Some("bar"));
+assert_eq!("foo:bar".strip_prefix("bar"), None);
+assert_eq!("foofoo".strip_prefix("foo"), Some("foo"));
+
1.45.0 · source

pub fn strip_suffix<P>(&self, suffix: P) -> Option<&str>
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns a string slice with the suffix removed.

+

If the string ends with the pattern suffix, returns the substring before the suffix, +wrapped in Some. Unlike trim_end_matches, this method removes the suffix exactly once.

+

If the string does not end with suffix, returns None.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Examples
+
assert_eq!("bar:foo".strip_suffix(":foo"), Some("bar"));
+assert_eq!("bar:foo".strip_suffix("bar"), None);
+assert_eq!("foofoo".strip_suffix("foo"), Some("foo"));
+
1.30.0 · source

pub fn trim_end_matches<P>(&self, pat: P) -> &str
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

Returns a string slice with all suffixes that match a pattern +repeatedly removed.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Text directionality
+

A string is a sequence of bytes. end in this context means the last +position of that byte string; for a left-to-right language like English or +Russian, this will be right side, and for right-to-left languages like +Arabic or Hebrew, this will be the left side.

+
§Examples
+

Simple patterns:

+ +
assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
+assert_eq!("123foo1bar123".trim_end_matches(char::is_numeric), "123foo1bar");
+
+let x: &[_] = &['1', '2'];
+assert_eq!("12foo1bar12".trim_end_matches(x), "12foo1bar");
+

A more complex pattern, using a closure:

+ +
assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo");
+
1.6.0 · source

pub fn trim_left_matches<P>(&self, pat: P) -> &str
where + P: Pattern,

👎Deprecated since 1.33.0: superseded by trim_start_matches

Returns a string slice with all prefixes that match a pattern +repeatedly removed.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Text directionality
+

A string is a sequence of bytes. ‘Left’ in this context means the first +position of that byte string; for a language like Arabic or Hebrew +which are ‘right to left’ rather than ‘left to right’, this will be +the right side, not the left.

+
§Examples
+
assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
+
+let x: &[_] = &['1', '2'];
+assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
+
1.6.0 · source

pub fn trim_right_matches<P>(&self, pat: P) -> &str
where + P: Pattern, + <P as Pattern>::Searcher<'a>: for<'a> ReverseSearcher<'a>,

👎Deprecated since 1.33.0: superseded by trim_end_matches

Returns a string slice with all suffixes that match a pattern +repeatedly removed.

+

The pattern can be a &str, char, a slice of chars, or a +function or closure that determines if a character matches.

+
§Text directionality
+

A string is a sequence of bytes. ‘Right’ in this context means the last +position of that byte string; for a language like Arabic or Hebrew +which are ‘right to left’ rather than ‘left to right’, this will be +the left side, not the right.

+
§Examples
+

Simple patterns:

+ +
assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
+assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
+
+let x: &[_] = &['1', '2'];
+assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+

A more complex pattern, using a closure:

+ +
assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
+
1.6.0 · source

pub fn parse<F>(&self) -> Result<F, <F as FromStr>::Err>
where + F: FromStr,

Parses this string slice into another type.

+

Because parse is so general, it can cause problems with type +inference. As such, parse is one of the few times you’ll see +the syntax affectionately known as the ‘turbofish’: ::<>. This +helps the inference algorithm understand specifically which type +you’re trying to parse into.

+

parse can parse into any type that implements the FromStr trait.

+
§Errors
+

Will return Err if it’s not possible to parse this string slice into +the desired type.

+
§Examples
+

Basic usage

+ +
let four: u32 = "4".parse().unwrap();
+
+assert_eq!(4, four);
+

Using the ‘turbofish’ instead of annotating four:

+ +
let four = "4".parse::<u32>();
+
+assert_eq!(Ok(4), four);
+

Failing to parse:

+ +
let nope = "j".parse::<u32>();
+
+assert!(nope.is_err());
+
1.23.0 · source

pub fn is_ascii(&self) -> bool

Checks if all characters in this string are within the ASCII range.

+
§Examples
+
let ascii = "hello!\n";
+let non_ascii = "Grüße, Jürgen ❤";
+
+assert!(ascii.is_ascii());
+assert!(!non_ascii.is_ascii());
+
source

pub fn as_ascii(&self) -> Option<&[AsciiChar]>

🔬This is a nightly-only experimental API. (ascii_char)

If this string slice is_ascii, returns it as a slice +of ASCII characters, otherwise returns None.

+
1.23.0 · source

pub fn eq_ignore_ascii_case(&self, other: &str) -> bool

Checks that two strings are an ASCII case-insensitive match.

+

Same as to_ascii_lowercase(a) == to_ascii_lowercase(b), +but without allocating and copying temporaries.

+
§Examples
+
assert!("Ferris".eq_ignore_ascii_case("FERRIS"));
+assert!("Ferrös".eq_ignore_ascii_case("FERRöS"));
+assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
+
1.80.0 · source

pub fn trim_ascii_start(&self) -> &str

Returns a string slice with leading ASCII whitespace removed.

+

‘Whitespace’ refers to the definition used by +u8::is_ascii_whitespace.

+
§Examples
+
assert_eq!(" \t \u{3000}hello world\n".trim_ascii_start(), "\u{3000}hello world\n");
+assert_eq!("  ".trim_ascii_start(), "");
+assert_eq!("".trim_ascii_start(), "");
+
1.80.0 · source

pub fn trim_ascii_end(&self) -> &str

Returns a string slice with trailing ASCII whitespace removed.

+

‘Whitespace’ refers to the definition used by +u8::is_ascii_whitespace.

+
§Examples
+
assert_eq!("\r hello world\u{3000}\n ".trim_ascii_end(), "\r hello world\u{3000}");
+assert_eq!("  ".trim_ascii_end(), "");
+assert_eq!("".trim_ascii_end(), "");
+
1.80.0 · source

pub fn trim_ascii(&self) -> &str

Returns a string slice with leading and trailing ASCII whitespace +removed.

+

‘Whitespace’ refers to the definition used by +u8::is_ascii_whitespace.

+
§Examples
+
assert_eq!("\r hello world\n ".trim_ascii(), "hello world");
+assert_eq!("  ".trim_ascii(), "");
+assert_eq!("".trim_ascii(), "");
+
1.34.0 · source

pub fn escape_debug(&self) -> EscapeDebug<'_>

Returns an iterator that escapes each char in self with char::escape_debug.

+

Note: only extended grapheme codepoints that begin the string will be +escaped.

+
§Examples
+

As an iterator:

+ +
for c in "❤\n!".escape_debug() {
+    print!("{c}");
+}
+println!();
+

Using println! directly:

+ +
println!("{}", "❤\n!".escape_debug());
+

Both are equivalent to:

+ +
println!("❤\\n!");
+

Using to_string:

+ +
assert_eq!("❤\n!".escape_debug().to_string(), "❤\\n!");
+
1.34.0 · source

pub fn escape_default(&self) -> EscapeDefault<'_>

Returns an iterator that escapes each char in self with char::escape_default.

+
§Examples
+

As an iterator:

+ +
for c in "❤\n!".escape_default() {
+    print!("{c}");
+}
+println!();
+

Using println! directly:

+ +
println!("{}", "❤\n!".escape_default());
+

Both are equivalent to:

+ +
println!("\\u{{2764}}\\n!");
+

Using to_string:

+ +
assert_eq!("❤\n!".escape_default().to_string(), "\\u{2764}\\n!");
+
1.34.0 · source

pub fn escape_unicode(&self) -> EscapeUnicode<'_>

Returns an iterator that escapes each char in self with char::escape_unicode.

+
§Examples
+

As an iterator:

+ +
for c in "❤\n!".escape_unicode() {
+    print!("{c}");
+}
+println!();
+

Using println! directly:

+ +
println!("{}", "❤\n!".escape_unicode());
+

Both are equivalent to:

+ +
println!("\\u{{2764}}\\u{{a}}\\u{{21}}");
+

Using to_string:

+ +
assert_eq!("❤\n!".escape_unicode().to_string(), "\\u{2764}\\u{a}\\u{21}");
+
source

pub fn substr_range(&self, substr: &str) -> Option<Range<usize>>

🔬This is a nightly-only experimental API. (substr_range)

Returns the range that a substring points to.

+

Returns None if substr does not point within self.

+

Unlike str::find, this does not search through the string. +Instead, it uses pointer arithmetic to find where in the string +substr is derived from.

+

This is useful for extending str::split and similar methods.

+

Note that this method may return false positives (typically either +Some(0..0) or Some(self.len()..self.len())) if substr is a +zero-length str that points at the beginning or end of another, +independent, str.

+
§Examples
+
#![feature(substr_range)]
+
+let data = "a, b, b, a";
+let mut iter = data.split(", ").map(|s| data.substr_range(s).unwrap());
+
+assert_eq!(iter.next(), Some(0..1));
+assert_eq!(iter.next(), Some(3..4));
+assert_eq!(iter.next(), Some(6..7));
+assert_eq!(iter.next(), Some(9..10));
+
source

pub fn as_str(&self) -> &str

🔬This is a nightly-only experimental API. (str_as_str)

Returns the same string as a string slice &str.

+

This method is redundant when used directly on &str, but +it helps dereferencing other string-like types to string slices, +for example references to Box<str> or Arc<str>.

+
1.36.0 · source

pub fn replace<P>(&self, from: P, to: &str) -> String
where + P: Pattern,

Replaces all matches of a pattern with another string.

+

replace creates a new String, and copies the data from this string slice into it. +While doing so, it attempts to find matches of a pattern. If it finds any, it +replaces them with the replacement string slice.

+
§Examples
+

Basic usage:

+ +
let s = "this is old";
+
+assert_eq!("this is new", s.replace("old", "new"));
+assert_eq!("than an old", s.replace("is", "an"));
+

When the pattern doesn’t match, it returns this string slice as String:

+ +
let s = "this is old";
+assert_eq!(s, s.replace("cookie monster", "little lamb"));
+
1.36.0 · source

pub fn replacen<P>(&self, pat: P, to: &str, count: usize) -> String
where + P: Pattern,

Replaces first N matches of a pattern with another string.

+

replacen creates a new String, and copies the data from this string slice into it. +While doing so, it attempts to find matches of a pattern. If it finds any, it +replaces them with the replacement string slice at most count times.

+
§Examples
+

Basic usage:

+ +
let s = "foo foo 123 foo";
+assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
+assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
+assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
+

When the pattern doesn’t match, it returns this string slice as String:

+ +
let s = "this is old";
+assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
+
1.36.0 · source

pub fn to_lowercase(&self) -> String

Returns the lowercase equivalent of this string slice, as a new String.

+

‘Lowercase’ is defined according to the terms of the Unicode Derived Core Property +Lowercase.

+

Since some characters can expand into multiple characters when changing +the case, this function returns a String instead of modifying the +parameter in-place.

+
§Examples
+

Basic usage:

+ +
let s = "HELLO";
+
+assert_eq!("hello", s.to_lowercase());
+

A tricky example, with sigma:

+ +
let sigma = "Σ";
+
+assert_eq!("σ", sigma.to_lowercase());
+
+// but at the end of a word, it's ς, not σ:
+let odysseus = "ὈΔΥΣΣΕΎΣ";
+
+assert_eq!("ὀδυσσεύς", odysseus.to_lowercase());
+

Languages without case are not changed:

+ +
let new_year = "农历新年";
+
+assert_eq!(new_year, new_year.to_lowercase());
+
1.36.0 · source

pub fn to_uppercase(&self) -> String

Returns the uppercase equivalent of this string slice, as a new String.

+

‘Uppercase’ is defined according to the terms of the Unicode Derived Core Property +Uppercase.

+

Since some characters can expand into multiple characters when changing +the case, this function returns a String instead of modifying the +parameter in-place.

+
§Examples
+

Basic usage:

+ +
let s = "hello";
+
+assert_eq!("HELLO", s.to_uppercase());
+

Scripts without case are not changed:

+ +
let new_year = "农历新年";
+
+assert_eq!(new_year, new_year.to_uppercase());
+

One character can become multiple:

+ +
let s = "tschüß";
+
+assert_eq!("TSCHÜSS", s.to_uppercase());
+
1.36.0 · source

pub fn repeat(&self, n: usize) -> String

Creates a new String by repeating a string n times.

+
§Panics
+

This function will panic if the capacity would overflow.

+
§Examples
+

Basic usage:

+ +
assert_eq!("abc".repeat(4), String::from("abcabcabcabc"));
+

A panic upon overflow:

+ +
// this will panic at runtime
+let huge = "0123456789abcdef".repeat(usize::MAX);
+
1.36.0 · source

pub fn to_ascii_uppercase(&self) -> String

Returns a copy of this string where each character is mapped to its +ASCII upper case equivalent.

+

ASCII letters ‘a’ to ‘z’ are mapped to ‘A’ to ‘Z’, +but non-ASCII letters are unchanged.

+

To uppercase the value in-place, use make_ascii_uppercase.

+

To uppercase ASCII characters in addition to non-ASCII characters, use +to_uppercase.

+
§Examples
+
let s = "Grüße, Jürgen ❤";
+
+assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
+
1.36.0 · source

pub fn to_ascii_lowercase(&self) -> String

Returns a copy of this string where each character is mapped to its +ASCII lower case equivalent.

+

ASCII letters ‘A’ to ‘Z’ are mapped to ‘a’ to ‘z’, +but non-ASCII letters are unchanged.

+

To lowercase the value in-place, use make_ascii_lowercase.

+

To lowercase ASCII characters in addition to non-ASCII characters, use +to_lowercase.

+
§Examples
+
let s = "Grüße, Jürgen ❤";
+
+assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
+

Trait Implementations§

source§

impl AsRef<[u8]> for ByteString

source§

fn as_ref(&self) -> &[u8]

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl AsRef<ByteString> for ByteString

source§

fn as_ref(&self) -> &ByteString

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl AsRef<str> for ByteString

source§

fn as_ref(&self) -> &str

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl Borrow<str> for ByteString

source§

fn borrow(&self) -> &str

Immutably borrows from an owned value. Read more
source§

impl Clone for ByteString

source§

fn clone(&self) -> ByteString

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for ByteString

source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for ByteString

source§

fn default() -> ByteString

Returns the “default value” for a type. Read more
source§

impl Deref for ByteString

source§

type Target = str

The resulting type after dereferencing.
source§

fn deref(&self) -> &str

Dereferences the value.
source§

impl<'de> Deserialize<'de> for ByteString

source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where + D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Display for ByteString

source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<&str> for ByteString

source§

fn from(value: &str) -> Self

Converts to this type from the input type.
source§

impl From<Box<str>> for ByteString

source§

fn from(value: Box<str>) -> Self

Converts to this type from the input type.
source§

impl From<ByteString> for String

source§

fn from(value: ByteString) -> Self

Converts to this type from the input type.
source§

impl From<String> for ByteString

source§

fn from(value: String) -> Self

Converts to this type from the input type.
source§

impl Hash for ByteString

source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.6.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where + H: Hasher, + Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for ByteString

source§

fn cmp(&self, other: &ByteString) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized,

Restrict a value to a certain interval. Read more
source§

impl<T: AsRef<str>> PartialEq<T> for ByteString

source§

fn eq(&self, other: &T) -> bool

Tests for self and other values to be equal, and is used by ==.
1.6.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl PartialEq<str> for ByteString

source§

fn eq(&self, other: &str) -> bool

Tests for self and other values to be equal, and is used by ==.
1.6.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl PartialOrd for ByteString

source§

fn partial_cmp(&self, other: &ByteString) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.6.0 · source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.6.0 · source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the +<= operator. Read more
1.6.0 · source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > +operator. Read more
1.6.0 · source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by +the >= operator. Read more
source§

impl Serialize for ByteString

source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where + S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl TryFrom<&[u8]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 0]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 0]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 1]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 1]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 10]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 10]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 11]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 11]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 12]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 12]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 13]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 13]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 14]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 14]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 15]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 15]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 16]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 16]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 17]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 17]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 18]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 18]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 19]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 19]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 2]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 2]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 20]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 20]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 21]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 21]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 22]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 22]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 23]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 23]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 24]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 24]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 25]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 25]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 26]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 26]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 27]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 27]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 28]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 28]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 29]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 29]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 3]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 3]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 30]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 30]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 31]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 31]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 32]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 32]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 4]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 4]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 5]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 5]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 6]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 6]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 7]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 7]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 8]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 8]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<&[u8; 9]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: &[u8; 9]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 0]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 0]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 1]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 1]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 10]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 10]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 11]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 11]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 12]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 12]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 13]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 13]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 14]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 14]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 15]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 15]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 16]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 16]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 17]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 17]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 18]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 18]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 19]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 19]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 2]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 2]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 20]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 20]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 21]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 21]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 22]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 22]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 23]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 23]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 24]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 24]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 25]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 25]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 26]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 26]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 27]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 27]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 28]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 28]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 29]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 29]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 3]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 3]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 30]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 30]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 31]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 31]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 32]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 32]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 4]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 4]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 5]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 5]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 6]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 6]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 7]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 7]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 8]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 8]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<[u8; 9]> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: [u8; 9]) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<Bytes> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: Bytes) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<BytesMut> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: BytesMut) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl TryFrom<Vec<u8>> for ByteString

source§

type Error = Utf8Error

The type returned in the event of a conversion error.
source§

fn try_from(value: Vec<u8>) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl Eq for ByteString

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> DeserializeOwned for T
where + T: for<'de> Deserialize<'de>,

\ No newline at end of file diff --git a/crates.js b/crates.js new file mode 100644 index 00000000..5467e626 --- /dev/null +++ b/crates.js @@ -0,0 +1,2 @@ +window.ALL_CRATES = ["actix_codec","actix_macros","actix_rt","actix_server","actix_service","actix_tls","actix_tracing","actix_utils","bytestring","local_channel","local_waker"]; +//{"start":21,"fragment_lengths":[13,15,11,15,16,12,16,14,13,16,14]} \ No newline at end of file diff --git a/help.html b/help.html new file mode 100644 index 00000000..531c35e8 --- /dev/null +++ b/help.html @@ -0,0 +1 @@ +Help

Rustdoc help

Back
\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..76105d1f --- /dev/null +++ b/index.html @@ -0,0 +1 @@ + diff --git a/local_channel/all.html b/local_channel/all.html new file mode 100644 index 00000000..f3ff709a --- /dev/null +++ b/local_channel/all.html @@ -0,0 +1 @@ +List of all items in this crate
\ No newline at end of file diff --git a/local_channel/index.html b/local_channel/index.html new file mode 100644 index 00000000..8a2a2fc0 --- /dev/null +++ b/local_channel/index.html @@ -0,0 +1,3 @@ +local_channel - Rust

Crate local_channel

source
Expand description

Non-thread-safe channels.

+

See docs for mpsc::channel().

+

Modules§

  • A non-thread-safe multi-producer, single-consumer, futures-aware, FIFO queue.
\ No newline at end of file diff --git a/local_channel/mpsc/fn.channel.html b/local_channel/mpsc/fn.channel.html new file mode 100644 index 00000000..6d749886 --- /dev/null +++ b/local_channel/mpsc/fn.channel.html @@ -0,0 +1,3 @@ +channel in local_channel::mpsc - Rust
local_channel::mpsc

Function channel

source
pub fn channel<T>() -> (Sender<T>, Receiver<T>)
Expand description

Creates a unbounded in-memory channel with buffered storage.

+

Senders and Receivers are !Send.

+
\ No newline at end of file diff --git a/local_channel/mpsc/index.html b/local_channel/mpsc/index.html new file mode 100644 index 00000000..0fed2c8e --- /dev/null +++ b/local_channel/mpsc/index.html @@ -0,0 +1,2 @@ +local_channel::mpsc - Rust
local_channel

Module mpsc

source
Expand description

A non-thread-safe multi-producer, single-consumer, futures-aware, FIFO queue.

+

Structs§

  • The receiving end of a channel which implements the Stream trait.
  • Error returned when attempting to send after the channels’ Receiver is dropped or closed.
  • The transmission end of a channel.

Functions§

  • Creates a unbounded in-memory channel with buffered storage.
\ No newline at end of file diff --git a/local_channel/mpsc/sidebar-items.js b/local_channel/mpsc/sidebar-items.js new file mode 100644 index 00000000..6627a3ac --- /dev/null +++ b/local_channel/mpsc/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":["channel"],"struct":["Receiver","SendError","Sender"]}; \ No newline at end of file diff --git a/local_channel/mpsc/struct.Receiver.html b/local_channel/mpsc/struct.Receiver.html new file mode 100644 index 00000000..78808b16 --- /dev/null +++ b/local_channel/mpsc/struct.Receiver.html @@ -0,0 +1,27 @@ +Receiver in local_channel::mpsc - Rust
local_channel::mpsc

Struct Receiver

source
pub struct Receiver<T> { /* private fields */ }
Expand description

The receiving end of a channel which implements the Stream trait.

+

This is created by the channel function.

+

Implementations§

source§

impl<T> Receiver<T>

source

pub async fn recv(&mut self) -> Option<T>

Receive the next value.

+

Returns None if the channel is empty and has been closed explicitly or +when all senders have been dropped and, therefore, no more values can ever be sent though +this channel.

+
source

pub fn sender(&self) -> Sender<T>

Create an associated Sender.

+

Trait Implementations§

source§

impl<T: Debug> Debug for Receiver<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T> Drop for Receiver<T>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<T> Stream for Receiver<T>

source§

type Item = T

Values yielded by the stream.
source§

fn poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, +) -> Poll<Option<Self::Item>>

Attempt to pull out the next value of this stream, registering the +current task for wakeup if the value is not yet available, and returning +None if the stream is exhausted. Read more
§

fn size_hint(&self) -> (usize, Option<usize>)

Returns the bounds on the remaining length of the stream. Read more
source§

impl<T> Unpin for Receiver<T>

Auto Trait Implementations§

§

impl<T> Freeze for Receiver<T>

§

impl<T> !RefUnwindSafe for Receiver<T>

§

impl<T> !Send for Receiver<T>

§

impl<T> !Sync for Receiver<T>

§

impl<T> !UnwindSafe for Receiver<T>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<S, T, E> TryStream for S
where + S: Stream<Item = Result<T, E>> + ?Sized,

§

type Ok = T

The type of successful values yielded by this future
§

type Error = E

The type of failures yielded by this future
§

fn try_poll_next( + self: Pin<&mut S>, + cx: &mut Context<'_>, +) -> Poll<Option<Result<<S as TryStream>::Ok, <S as TryStream>::Error>>>

Poll this TryStream as if it were a Stream. Read more
\ No newline at end of file diff --git a/local_channel/mpsc/struct.SendError.html b/local_channel/mpsc/struct.SendError.html new file mode 100644 index 00000000..79ee6eb6 --- /dev/null +++ b/local_channel/mpsc/struct.SendError.html @@ -0,0 +1,21 @@ +SendError in local_channel::mpsc - Rust
local_channel::mpsc

Struct SendError

source
pub struct SendError<T>(pub T);
Expand description

Error returned when attempting to send after the channels’ Receiver is dropped or closed.

+

Allows access to message that failed to send with into_inner.

+

Tuple Fields§

§0: T

Implementations§

source§

impl<T> SendError<T>

source

pub fn into_inner(self) -> T

Returns the message that was attempted to be sent but failed.

+

Trait Implementations§

source§

impl<T> Debug for SendError<T>

source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T> Display for SendError<T>

source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T> Error for SendError<T>

1.81.0 · source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.81.0 · source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
1.81.0 · source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more

Auto Trait Implementations§

§

impl<T> Freeze for SendError<T>
where + T: Freeze,

§

impl<T> RefUnwindSafe for SendError<T>
where + T: RefUnwindSafe,

§

impl<T> Send for SendError<T>
where + T: Send,

§

impl<T> Sync for SendError<T>
where + T: Sync,

§

impl<T> Unpin for SendError<T>
where + T: Unpin,

§

impl<T> UnwindSafe for SendError<T>
where + T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToString for T
where + T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/local_channel/mpsc/struct.Sender.html b/local_channel/mpsc/struct.Sender.html new file mode 100644 index 00000000..8def5609 --- /dev/null +++ b/local_channel/mpsc/struct.Sender.html @@ -0,0 +1,30 @@ +Sender in local_channel::mpsc - Rust
local_channel::mpsc

Struct Sender

source
pub struct Sender<T> { /* private fields */ }
Expand description

The transmission end of a channel.

+

This is created by the channel function.

+

Implementations§

source§

impl<T> Sender<T>

source

pub fn send(&self, item: T) -> Result<(), SendError<T>>

Sends the provided message along this channel.

+
source

pub fn close(&mut self)

Closes the sender half.

+

This prevents any further messages from being sent on the channel, by any sender, while +still enabling the receiver to drain messages that are already buffered.

+

Trait Implementations§

source§

impl<T> Clone for Sender<T>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug> Debug for Sender<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T> Drop for Sender<T>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<T> Sink<T> for Sender<T>

source§

type Error = SendError<T>

The type of value produced by the sink when an error occurs.
source§

fn poll_ready( + self: Pin<&mut Self>, + _: &mut Context<'_>, +) -> Poll<Result<(), Self::Error>>

Attempts to prepare the Sink to receive a value. Read more
source§

fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), SendError<T>>

Begin the process of sending a value to the sink. +Each call to this function must be preceded by a successful call to +poll_ready which returned Poll::Ready(Ok(())). Read more
source§

fn poll_flush( + self: Pin<&mut Self>, + _: &mut Context<'_>, +) -> Poll<Result<(), SendError<T>>>

Flush any remaining output from this sink. Read more
source§

fn poll_close( + self: Pin<&mut Self>, + _: &mut Context<'_>, +) -> Poll<Result<(), Self::Error>>

Flush any remaining output and close this sink, if necessary. Read more
source§

impl<T> Unpin for Sender<T>

Auto Trait Implementations§

§

impl<T> Freeze for Sender<T>

§

impl<T> !RefUnwindSafe for Sender<T>

§

impl<T> !Send for Sender<T>

§

impl<T> !Sync for Sender<T>

§

impl<T> !UnwindSafe for Sender<T>

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/local_channel/sidebar-items.js b/local_channel/sidebar-items.js new file mode 100644 index 00000000..5eeb7b67 --- /dev/null +++ b/local_channel/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"mod":["mpsc"]}; \ No newline at end of file diff --git a/local_waker/all.html b/local_waker/all.html new file mode 100644 index 00000000..b8a0141b --- /dev/null +++ b/local_waker/all.html @@ -0,0 +1 @@ +List of all items in this crate

List of all items

Structs

\ No newline at end of file diff --git a/local_waker/index.html b/local_waker/index.html new file mode 100644 index 00000000..c6e013fa --- /dev/null +++ b/local_waker/index.html @@ -0,0 +1,3 @@ +local_waker - Rust

Crate local_waker

source
Expand description

A synchronization primitive for thread-local task wakeup.

+

See docs for LocalWaker.

+

Structs§

  • A synchronization primitive for task wakeup.
\ No newline at end of file diff --git a/local_waker/sidebar-items.js b/local_waker/sidebar-items.js new file mode 100644 index 00000000..4b28c5cf --- /dev/null +++ b/local_waker/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":["LocalWaker"]}; \ No newline at end of file diff --git a/local_waker/struct.LocalWaker.html b/local_waker/struct.LocalWaker.html new file mode 100644 index 00000000..5aa80e22 --- /dev/null +++ b/local_waker/struct.LocalWaker.html @@ -0,0 +1,29 @@ +LocalWaker in local_waker - Rust
local_waker

Struct LocalWaker

source
pub struct LocalWaker { /* private fields */ }
Expand description

A synchronization primitive for task wakeup.

+

Sometimes the task interested in a given event will change over time. A LocalWaker can +coordinate concurrent notifications with the consumer, potentially “updating” the underlying +task to wake up. This is useful in scenarios where a computation completes in another task and +wants to notify the consumer, but the consumer is in the process of being migrated to a new +logical task.

+

Consumers should call register before checking the result of a computation and producers +should call wake after producing the computation (this differs from the usual thread::park +pattern). It is also permitted for wake to be called before register. This results in +a no-op.

+

A single LocalWaker may be reused for any number of calls to register or wake.

+

Implementations§

source§

impl LocalWaker

source

pub fn new() -> Self

Creates a new, empty LocalWaker.

+
source

pub fn register(&self, waker: &Waker) -> bool

Registers the waker to be notified on calls to wake.

+

Returns true if waker was registered before.

+
source

pub fn wake(&self)

Calls wake on the last Waker passed to register.

+

If register has not been called yet, then this does nothing.

+
source

pub fn take(&self) -> Option<Waker>

Returns the last Waker passed to register, so that the user can wake it.

+

If a waker has not been registered, this returns None.

+

Trait Implementations§

source§

impl Debug for LocalWaker

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for LocalWaker

source§

fn default() -> LocalWaker

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+

That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

+
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
\ No newline at end of file diff --git a/search-index.js b/search-index.js new file mode 100644 index 00000000..60dea389 --- /dev/null +++ b/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = new Map(JSON.parse('[["actix_codec",{"t":"KKFKKRRFFRFFNNNNNNNNNNNNNNNNNNNNNONNMNNNNNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNMNNMHNMMNNONNNNNNNNNNNNNNNNNNNNNNNNNNNO","n":["AsyncRead","AsyncWrite","BytesCodec","Decoder","Encoder","Error","","Framed","FramedParts","Item","LinesCodec","ReadBuf","advance","assume_init","borrow","","","","","borrow_mut","","","","","capacity","clear","clone","","clone_into","","clone_to_uninit","","close","codec","codec_mut","codec_ref","decode","","","decode_eof","","default","encode","","","filled","filled_mut","flush","fmt","","","","","framed","from","","","","","from_parts","initialize_unfilled","initialize_unfilled_to","initialized","initialized_mut","inner_mut","into","","","","","into_map_codec","into_map_io","into_parts","io","io_mut","io_pin","io_ref","is_read_buf_empty","is_write_buf_empty","is_write_buf_full","is_write_ready","is_write_vectored","new","","","next_item","poll_close","poll_flush","","poll_next","poll_read","poll_read_buf","poll_ready","poll_shutdown","poll_write","poll_write_vectored","put_slice","read_buf","remaining","replace_codec","set_filled","start_send","take","to_owned","","try_from","","","","","try_into","","","","","try_poll_next","type_id","","","","","unfilled_mut","uninit","with_read_buf","write","write_buf"],"q":[[0,"actix_codec"],[126,"tokio::io::read_buf"],[127,"actix_codec::bcodec"],[128,"actix_codec::lines"],[129,"actix_codec::framed"],[130,"core::pin"],[131,"core::task::wake"],[132,"core::result"],[133,"core::task::poll"],[134,"tokio::io::async_write"],[135,"tokio_util::codec::encoder"],[136,"tokio_util::codec::decoder"],[137,"bytes::bytes_mut"],[138,"core::option"],[139,"std::io::error"],[140,"core::convert"],[141,"bytes::bytes"],[142,"core::fmt"],[143,"tokio_util::codec::framed"],[144,"tokio::io::async_read"],[145,"core::mem::maybe_uninit"],[146,"core::ops::function"],[147,"core::marker"],[148,"bytes::buf::buf_mut"],[149,"std::io"],[150,"core::any"],[151,"tokio_util::util::poll_buf"]],"i":"`````BbAl``1``d0l1A`Cnn34210443030302122630600530442342106342102444443421022212222222Aj53233033Db`4111636464652564325643245643266343","f":"````````````{{{f{bd}}h}j}0{f{{f{c}}}{}}0000{{{f{b}}}{{f{bc}}}{}}0000{{{f{d}}}h}{{{f{bd}}}j}{{{f{l}}}l}{{{f{n}}}n}{{f{f{bc}}}j{}}0{fj}0{{{Ab{{f{b{A`{cg}}}}}}{f{bAd}}}{{Ah{{Af{j}}}}}Aj{}{{Al{e}}}}`{{{f{b{A`{ce}}}}}{{f{be}}}{}{}}{{{f{{A`{ce}}}}}{{f{e}}}{}{}}{{{f{b{Bb{}{{An{c}}{B`{e}}}}}}{f{bBd}}}{{Af{{Bf{c}}e}}}{}{{Bj{Bh}}}}{{{f{bl}}{f{bBd}}}{{Af{{Bf{c}}e}}}{}{}}{{{f{bn}}{f{bBd}}}{{Af{{Bf{c}}e}}}{}{}}20{{}n}{{{f{b{Al{}{{B`{c}}}}}}e{f{bBd}}}{{Af{jc}}}{{Bj{Bh}}}{}}{{{f{bl}}Bl{f{bBd}}}{{Af{jc}}}{}}{{{f{bn}}c{f{bBd}}}{{Af{je}}}{{C`{Bn}}}{}}{{{f{d}}}{{f{{Cd{Cb}}}}}}{{{f{bd}}}{{f{b{Cd{Cb}}}}}};{{{f{l}}{f{bCf}}}Ch}{{{f{d}}{f{bCf}}}{{Af{jCj}}}}{{{f{{A`{ce}}}}{f{bCf}}}ChClCl}{{{f{{Cn{ce}}}}{f{bCf}}}ChClCl}{{{f{n}}{f{bCf}}}Ch}{{{Bb{}{{An{c}}{B`{e}}}}g}{{D`{g{Bb{}{{An{c}}{B`{e}}}}}}}{}{{Bj{Bh}}}{DbAj}}{cc{}}0000{{{Cn{ce}}}{{A`{ce}}}{}{}}8{{{f{bd}}h}{{f{b{Cd{Cb}}}}}}:9{{{f{bd}}}{{f{b{Cd{{Dd{Cb}}}}}}}}{{}c{}}0000{{{A`{ce}}i}{{A`{cg}}}{}{}{}{{Dh{e}{{Df{g}}}}}}{{{A`{ce}}i}{{A`{ge}}}{}{}{}{{Dh{c}{{Df{g}}}}}}{{{A`{ce}}}{{Cn{ce}}}{}{}}`{{{f{b{A`{ce}}}}}{{f{bc}}}{}{}}{{{Ab{{f{b{A`{ce}}}}}}}{{Ab{{f{bc}}}}}{}{}}{{{f{{A`{ce}}}}}{{f{c}}}{}{}}{{{f{{A`{ce}}}}}Dj{}{}}000{{{f{Aj}}}Dj}{{{f{b{Cd{Cb}}}}}d}{{ce}{{A`{ce}}}{DbAj}Bb}{{ce}{{Cn{ce}}}{}{}}{{{Ab{{f{b{A`{ce}}}}}}{f{bAd}}}{{Ah{{Bf{Af}}}}}DbBb}{{{Ab{{f{b{A`{cg}}}}}}{f{bAd}}}{{Ah{{Af{ji}}}}}Aj{}{{Al{e}}}{}}{{{Ab{{f{bAj}}}}{f{bAd}}}{{Ah{{Af{jBh}}}}}}1{{{Ab{{f{b{A`{ce}}}}}}{f{bAd}}}{{Ah{{Bf{g}}}}}DbBb{}}{{{Ab{{f{bDb}}}}{f{bAd}}{f{bd}}}{{Ah{{Af{jBh}}}}}}{{{Ab{{f{bc}}}}{f{bAd}}{f{be}}}{{Ah{{Af{hBh}}}}}{DbDl}Dn}43{{{Ab{{f{bAj}}}}{f{bAd}}{f{{Cd{Cb}}}}}{{Ah{{Af{hBh}}}}}}{{{Ab{{f{bAj}}}}{f{bAd}}{f{{Cd{E`}}}}}{{Ah{{Af{hBh}}}}}}{{{f{bd}}{f{{Cd{Cb}}}}}j}`{{{f{d}}}h}{{{A`{ce}}g}{{A`{cg}}}{}{}{}}{{{f{bd}}h}j}{{{Ab{{f{b{A`{cg}}}}}}e}{{Af{ji}}}Aj{}{{Al{e}}}{}}{{{f{bd}}h}d}{fc{}}0{c{{Af{e}}}{}{}}0000{{}{{Af{c}}}{}}0000{{{Ab{{f{bc}}}}{f{bAd}}}{{Ah{{Bf{Af}}}}}{}}{fEb}0000{{{f{bd}}}{{f{b{Cd{{Dd{Cb}}}}}}}}{{{f{b{Cd{{Dd{Cb}}}}}}}d}{{ceBd}{{Cn{ce}}}{}{}}{{{Ab{{f{b{A`{cg}}}}}}e}{{Af{j}}}Aj{}{{Al{e}}}}`","D":"Ij","p":[[0,"mut"],[5,"ReadBuf",0,126],[1,"reference"],[1,"usize"],[1,"unit"],[5,"BytesCodec",0,127],[5,"LinesCodec",0,128],[5,"Framed",0,129],[5,"Pin",130],[5,"Context",131],[6,"Result",132],[6,"Poll",133],[10,"AsyncWrite",0,134],[10,"Encoder",0,135],[17,"Item"],[17,"Error"],[10,"Decoder",0,136],[5,"BytesMut",137],[6,"Option",138],[5,"Error",139],[10,"From",140],[5,"Bytes",141],[1,"str"],[10,"AsRef",140],[1,"u8"],[1,"slice"],[5,"Formatter",142],[8,"Result",142],[5,"Error",142],[10,"Debug",142],[5,"FramedParts",0,129],[5,"Framed",143],[10,"AsyncRead",0,144],[20,"MaybeUninit",145],[17,"Output"],[10,"Fn",146],[1,"bool"],[10,"Sized",147],[10,"BufMut",148],[5,"IoSlice",149],[5,"TypeId",150]],"r":[[0,144],[1,134],[2,127],[3,136],[4,135],[7,129],[8,129],[10,128],[11,126],[91,151]],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAADEACwAPAAkAGwAFACYAAQApAAEALAABADEABABXAAAAWQABAF0AAABmAAAAaAARAA=="}],["actix_macros",{"t":"XX","n":["main","test"],"q":[[0,"actix_macros"]],"i":"``","f":"``","D":"f","p":[],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OjAAAAAAAAA="}],["actix_rt",{"t":"FFFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNXCNNNQNNCHNNNNNNNNNCXCNNNNNNNNNNNNNNNNNNNNTTTTTTFFFFFFFFTTNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHCFFNNNNNNNNNNNNNNNNNNNNNNNNNNNHNNNNNNNNNNNFFNNNNNNNNNNNNNNNNNNNNHNNNNNNNNNHFFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHHNNNNNNNNNNNNNNNNNNNNNNNHHNNNNHNNNNNNNNNNNNNN","n":["Arbiter","ArbiterHandle","Runtime","System","SystemRunner","arbiter","block_on","","borrow","","","","","borrow_mut","","","","","clone","","clone_into","","clone_to_uninit","","current","","fmt","","","","","from","","","","","","handle","id","into","","","","","is_registered","join","main","net","new","","","pin","run","run_with_code","signal","spawn","","","","spawn_fn","","stop","","","stop_with_code","task","test","time","to_owned","","tokio_runtime","try_current","","try_from","","","","","try_into","","","","","type_id","","","","","ALL","EMPTY","ERROR","PRIORITY","READABLE","READ_CLOSED","Ready","TcpListener","TcpSocket","TcpStream","UdpSocket","UnixDatagram","UnixListener","UnixStream","WRITABLE","WRITE_CLOSED","accept","","as_fd","","","","","","","as_raw_fd","","","","","","","async_io","","","","bind","","","","","bind_device","","bitand","bitor","bitor_assign","borrow","","","","","","","","borrow_mut","","","","","","","","broadcast","clone","clone_into","clone_to_uninit","cmp","connect","","","","","device","","eq","fmt","","","","","","","","from","","","","","","","","from_raw_fd","from_std","","","","","","from_std_stream","into","","","","","","","","into_raw_fd","into_split","","into_std","","","","","","is_empty","is_error","is_priority","is_read_closed","is_readable","is_writable","is_write_closed","is_write_vectored","","join_multicast_v4","join_multicast_v6","keepalive","leave_multicast_v4","leave_multicast_v6","linger","","listen","local_addr","","","","","","","multicast_loop_v4","multicast_loop_v6","multicast_ttl_v4","new_v4","new_v6","nodelay","","pair","","partial_cmp","peek","peek_from","peek_sender","peer_addr","","","","peer_cred","poll_accept","","poll_flush","","poll_peek","poll_peek_from","poll_peek_sender","poll_read","","poll_read_ready","","poll_recv","","poll_recv_from","","poll_recv_ready","","poll_send","","poll_send_ready","","poll_send_to","","poll_shutdown","","poll_write","","poll_write_ready","","poll_write_vectored","","readable","","","","ready","","","","recv","","recv_buffer_size","recv_from","","reuseaddr","reuseport","send","","send_buffer_size","send_to","","set_broadcast","set_keepalive","set_linger","","set_multicast_loop_v4","set_multicast_loop_v6","set_multicast_ttl_v4","set_nodelay","","set_recv_buffer_size","set_reuseaddr","set_reuseport","set_send_buffer_size","set_tos","","set_ttl","","","shutdown","split","","sub","take_error","","","","","","to_owned","tos","","try_from","","","","","","","","","","","","","","try_into","","","","","","","","try_io","","","","try_peek_from","try_peek_sender","try_read","","try_read_vectored","","try_recv","","try_recv_from","","try_send","","try_send_to","","try_write","","try_write_vectored","","ttl","","","type_id","","","","","","","","unbound","writable","","","","ctrl_c","unix","Signal","SignalKind","alarm","as_raw_value","borrow","","borrow_mut","","child","clone","clone_into","clone_to_uninit","eq","fmt","","from","","","from_raw","hangup","hash","interrupt","into","","io","pipe","poll_recv","quit","recv","signal","terminate","to_owned","try_from","","try_into","","type_id","","user_defined1","user_defined2","window_change","JoinError","JoinHandle","abort","abort_handle","borrow","","borrow_mut","","drop","fmt","","","from","","into","","into_future","into_panic","is_cancelled","is_finished","is_panic","poll","spawn_blocking","to_string","try_from","","try_into","","try_into_panic","try_poll","type_id","","yield_now","Instant","Interval","Sleep","Timeout","add","add_assign","borrow","","","","borrow_mut","","","","checked_add","checked_duration_since","checked_sub","clone","clone_into","clone_to_uninit","cmp","deadline","duration_since","elapsed","eq","fmt","","","","from","","","","","from_std","get_mut","get_ref","hash","interval","interval_at","into","","","","into_future","","into_inner","into_std","is_elapsed","missed_tick_behavior","now","partial_cmp","period","poll","","poll_tick","reset","","reset_after","reset_at","reset_immediately","saturating_duration_since","set_missed_tick_behavior","sleep","sleep_until","sub","","sub_assign","tick","timeout","to_owned","try_from","","","","try_into","","","","try_poll","type_id","","",""],"q":[[0,"actix_rt"],[88,"actix_rt::net"],[388,"actix_rt::signal"],[390,"actix_rt::signal::unix"],[431,"actix_rt::task"],[464,"actix_rt::time"],[548,"actix_rt::system"],[549,"actix_rt::arbiter"],[550,"actix_rt::runtime"],[551,"core::future::future"],[552,"core::fmt"],[553,"tokio::runtime::runtime"],[554,"std::thread"],[555,"std::io::error"],[556,"tokio::runtime::task::join"],[557,"core::marker"],[558,"core::ops::function"],[559,"core::option"],[560,"core::result"],[561,"core::any"],[562,"tokio::net::tcp::listener"],[563,"tokio::net::tcp::stream"],[564,"core::net::socket_addr"],[565,"tokio::net::unix::listener"],[566,"tokio::net::unix::stream"],[567,"tokio::net::unix::socketaddr"],[568,"std::os::fd::owned"],[569,"tokio::net::tcp::socket"],[570,"tokio::net::udp"],[571,"tokio::net::unix::datagram::socket"],[572,"tokio::io::interest"],[573,"tokio::net::addr"],[574,"std::path"],[575,"core::convert"],[576,"tokio::io::ready"],[577,"core::cmp"],[578,"alloc::vec"],[579,"std::net::tcp"],[580,"std::net::udp"],[581,"std::os::unix::net::datagram"],[582,"std::os::unix::net::listener"],[583,"std::os::unix::net::stream"],[584,"tokio::net::tcp::split_owned"],[585,"tokio::net::unix::split_owned"],[586,"core::net::ip_addr"],[587,"core::time"],[588,"tokio::net::unix::ucred"],[589,"core::task::wake"],[590,"core::task::poll"],[591,"core::pin"],[592,"tokio::io::read_buf"],[593,"std::io"],[594,"std::net"],[595,"tokio::net::tcp::split"],[596,"tokio::net::unix::split"],[597,"tokio::signal::unix"],[598,"core::hash"],[599,"tokio::runtime::task::abort"],[600,"tokio::runtime::task::error"],[601,"alloc::boxed"],[602,"alloc::string"],[603,"tokio::time::instant"],[604,"tokio::time::sleep"],[605,"tokio::time::interval"],[606,"tokio::time::timeout"],[607,"std::time"],[608,"core::future::into_future"],[609,"actix_macros"],[610,"tokio"],[611,"tokio::signal::ctrl_c"],[612,"tokio::task::blocking"],[613,"tokio::task::yield_now"]],"i":"`````bhlfAf342103421414140410342103342041034240``034`22``103101044```14304103421034210342Eh00000````````00CbCl1DdCdDfDh4Cn64321503210642154277776432150764321502777743210427764321507643215046321504764321504306321507777777302242243464321502224443107322321006530322303021212121212130303030321032102142144214212443222434444426321307432150742766433221155007643215032102230302121212130306327643215013210````Id00If10111111011011111011010`11101010111``Bd0Il10110010101100101`001010101`````Jf00JjJlJh3210333333303333210332103113``32101013023321022022232``3332`33210321013210","f":"`````{{{d{b}}}{{d{f}}}}{{{d{h}}c}{}j}{{{d{l}}c}{}j}{d{{d{c}}}{}}0000{{{d{n}}}{{d{nc}}}{}}0000{{{d{f}}}f}{{{d{b}}}b}{{d{d{nc}}}A`{}}0{dA`}0{{}f}{{}b}{{{d{f}}{d{nAb}}}Ad}{{{d{Af}}{d{nAb}}}Ad}{{{d{h}}{d{nAb}}}Ad}{{{d{b}}{d{nAb}}}Ad}{{{d{l}}{d{nAb}}}Ad}{cc{}}00{Ahh}11{{{d{Af}}}f}{{{d{b}}}Aj}{{}c{}}0000{{}Al}{Af{{An{A`}}}}``{{}Af}{{}{{B`{h}}}}{{}l}`{l{{B`{A`}}}}{l{{B`{Bb}}}}`{cBdj}{{{d{f}}c}Al{{j{}{{Bf{A`}}}}Bh}}{{{d{Af}}c}Al{{j{}{{Bf{A`}}}}Bh}}{{{d{h}}c}Bdj}{{{d{f}}c}Al{BjBh}}{{{d{Af}}c}Al{BjBh}}{{{d{f}}}Al}{{{d{Af}}}Al}{{{d{b}}}A`}{{{d{b}}Bb}A`}```{dc{}}0{{{d{h}}}{{d{Ah}}}}{{}{{Bl{f}}}}{{}{{Bl{b}}}}{c{{Bn{e}}}{}{}}0000{{}{{Bn{c}}}{}}0000{dC`}0000````````````````{{{d{Cb}}}{{Bn{{Ch{CdCf}}Cj}}}}{{{d{Cl}}}{{Bn{{Ch{CnD`}}Cj}}}}{{{d{Cb}}}Db}{{{d{Dd}}}Db}{{{d{Cd}}}Db}{{{d{Df}}}Db}{{{d{Dh}}}Db}{{{d{Cl}}}Db}{{{d{Cn}}}Db}{{{d{Cb}}}Bb}{{{d{Dd}}}Bb}{{{d{Cd}}}Bb}{{{d{Df}}}Bb}{{{d{Dh}}}Bb}{{{d{Cl}}}Bb}{{{d{Cn}}}Bb}{{{d{Cd}}Dje}{{Bn{cCj}}}{}{{Dl{}{{Bf{{Bn{cCj}}}}}}}}{{{d{Df}}Dje}{{Bn{cCj}}}{}{{Dl{}{{Bf{{Bn{cCj}}}}}}}}{{{d{Dh}}Dje}{{Bn{cCj}}}{}{{Dl{}{{Bf{{Bn{cCj}}}}}}}}{{{d{Cn}}Dje}{{Bn{cCj}}}{}{{Dl{}{{Bf{{Bn{cCj}}}}}}}}{c{{Bn{CbCj}}}Dn}{{{d{Dd}}Cf}{{Bn{A`Cj}}}}{c{{Bn{DfCj}}}Dn}{c{{Bn{DhCj}}}{{Eb{E`}}}}{c{{Bn{ClCj}}}{{Eb{E`}}}}{{{d{Dd}}{Bl{{d{{Ef{Ed}}}}}}}{{Bn{A`Cj}}}}{{{d{Df}}{Bl{{d{{Ef{Ed}}}}}}}{{Bn{A`Cj}}}}{{EhEh}Eh}0{{{d{nEh}}Eh}A`}{d{{d{c}}}{}}0000000{{{d{n}}}{{d{nc}}}{}}0000000{{{d{Df}}}{{Bn{AlCj}}}}{{{d{Eh}}}Eh}{{d{d{nc}}}A`{}}{dA`}{{{d{Eh}}{d{Eh}}}Ej}{{DdCf}{{Bn{CdCj}}}}{c{{Bn{CdCj}}}Dn}{{{d{Df}}c}{{Bn{A`Cj}}}Dn}{{{d{Dh}}c}{{Bn{A`Cj}}}{{Eb{E`}}}}{c{{Bn{CnCj}}}{{Eb{E`}}}}{{{d{Dd}}}{{Bn{{Bl{{El{Ed}}}}Cj}}}}{{{d{Df}}}{{Bn{{Bl{{El{Ed}}}}Cj}}}}{{{d{Eh}}{d{Eh}}}Al}{{{d{Eh}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Cb}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Dd}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Cd}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Df}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Dh}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Cl}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Cn}}{d{nAb}}}{{Bn{A`En}}}}{cc{}}0000000{BbDd}{F`{{Bn{CbCj}}}}{Fb{{Bn{CdCj}}}}{Fd{{Bn{DfCj}}}}{Ff{{Bn{DhCj}}}}{Fh{{Bn{ClCj}}}}{Fj{{Bn{CnCj}}}}{FbDd}{{}c{}}0000000{DdBb}{Cd{{Ch{FlFn}}}}{Cn{{Ch{G`Gb}}}}{Cb{{Bn{F`Cj}}}}{Cd{{Bn{FbCj}}}}{Df{{Bn{FdCj}}}}{Dh{{Bn{FfCj}}}}{Cl{{Bn{FhCj}}}}{Cn{{Bn{FjCj}}}}{EhAl}000000{{{d{Cd}}}Al}{{{d{Cn}}}Al}{{{d{Df}}GdGd}{{Bn{A`Cj}}}}{{{d{Df}}{d{Gf}}Gh}{{Bn{A`Cj}}}}{{{d{Dd}}}{{Bn{AlCj}}}}21{{{d{Dd}}}{{Bn{{Bl{Gj}}Cj}}}}{{{d{Cd}}}{{Bn{{Bl{Gj}}Cj}}}}{{DdGh}{{Bn{CbCj}}}}{{{d{Cb}}}{{Bn{CfCj}}}}{{{d{Dd}}}{{Bn{CfCj}}}}{{{d{Cd}}}{{Bn{CfCj}}}}{{{d{Df}}}{{Bn{CfCj}}}}{{{d{Dh}}}{{Bn{D`Cj}}}}{{{d{Cl}}}{{Bn{D`Cj}}}}{{{d{Cn}}}{{Bn{D`Cj}}}}{{{d{Df}}}{{Bn{AlCj}}}}0{{{d{Df}}}{{Bn{GhCj}}}}{{}{{Bn{DdCj}}}}0={{{d{Cd}}}{{Bn{AlCj}}}}{{}{{Bn{{Ch{DhDh}}Cj}}}}{{}{{Bn{{Ch{CnCn}}Cj}}}}{{{d{Eh}}{d{Eh}}}{{Bl{Ej}}}}{{{d{Cd}}{d{n{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Df}}{d{n{Ef{Ed}}}}}{{Bn{{Ch{AjCf}}Cj}}}}<=<;9{{{d{Cn}}}{{Bn{GlCj}}}}{{{d{Cb}}{d{nGn}}}{{H`{{Bn{{Ch{CdCf}}Cj}}}}}}{{{d{Cl}}{d{nGn}}}{{H`{{Bn{{Ch{CnD`}}Cj}}}}}}{{{Hb{{d{nCd}}}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{Hb{{d{nCn}}}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{d{Cd}}{d{nGn}}{d{nHd}}}{{H`{{Bn{AjCj}}}}}}{{{d{Df}}{d{nGn}}{d{nHd}}}{{H`{{Bn{CfCj}}}}}}{{{d{Df}}{d{nGn}}}{{H`{{Bn{CfCj}}}}}}{{{Hb{{d{nCd}}}}{d{nGn}}{d{nHd}}}{{H`{{Bn{A`Cj}}}}}}{{{Hb{{d{nCn}}}}{d{nGn}}{d{nHd}}}{{H`{{Bn{A`Cj}}}}}}{{{d{Cd}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{d{Cn}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{d{Df}}{d{nGn}}{d{nHd}}}{{H`{{Bn{A`Cj}}}}}}{{{d{Dh}}{d{nGn}}{d{nHd}}}{{H`{{Bn{A`Cj}}}}}}7{{{d{Dh}}{d{nGn}}{d{nHd}}}{{H`{{Bn{D`Cj}}}}}}{{{d{Df}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{d{Dh}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{d{Df}}{d{nGn}}{d{{Ef{Ed}}}}}{{H`{{Bn{AjCj}}}}}}{{{d{Dh}}{d{nGn}}{d{{Ef{Ed}}}}}{{H`{{Bn{AjCj}}}}}}32{{{d{Df}}{d{nGn}}{d{{Ef{Ed}}}}Cf}{{H`{{Bn{AjCj}}}}}}{{{d{Dh}}{d{nGn}}{d{{Ef{Ed}}}}c}{{H`{{Bn{AjCj}}}}}{{Eb{E`}}}}{{{Hb{{d{nCd}}}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{Hb{{d{nCn}}}}{d{nGn}}}{{H`{{Bn{A`Cj}}}}}}{{{Hb{{d{nCd}}}}{d{nGn}}{d{{Ef{Ed}}}}}{{H`{{Bn{AjCj}}}}}}{{{Hb{{d{nCn}}}}{d{nGn}}{d{{Ef{Ed}}}}}{{H`{{Bn{AjCj}}}}}}>={{{Hb{{d{nCd}}}}{d{nGn}}{d{{Ef{Hf}}}}}{{H`{{Bn{AjCj}}}}}}{{{Hb{{d{nCn}}}}{d{nGn}}{d{{Ef{Hf}}}}}{{H`{{Bn{AjCj}}}}}}{{{d{Cd}}}{{Bn{A`Cj}}}}{{{d{Df}}}{{Bn{A`Cj}}}}{{{d{Dh}}}{{Bn{A`Cj}}}}{{{d{Cn}}}{{Bn{A`Cj}}}}{{{d{Cd}}Dj}{{Bn{EhCj}}}}{{{d{Df}}Dj}{{Bn{EhCj}}}}{{{d{Dh}}Dj}{{Bn{EhCj}}}}{{{d{Cn}}Dj}{{Bn{EhCj}}}}{{{d{Df}}{d{n{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Dh}}{d{n{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Dd}}}{{Bn{GhCj}}}}{{{d{Df}}{d{n{Ef{Ed}}}}}{{Bn{{Ch{AjCf}}Cj}}}}{{{d{Dh}}{d{n{Ef{Ed}}}}}{{Bn{{Ch{AjD`}}Cj}}}}{{{d{Dd}}}{{Bn{AlCj}}}}0{{{d{Df}}{d{{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Dh}}{d{{Ef{Ed}}}}}{{Bn{AjCj}}}}5{{{d{Df}}{d{{Ef{Ed}}}}c}{{Bn{AjCj}}}Dn}{{{d{Dh}}{d{{Ef{Ed}}}}c}{{Bn{AjCj}}}{{Eb{E`}}}}{{{d{Df}}Al}{{Bn{A`Cj}}}}{{{d{Dd}}Al}{{Bn{A`Cj}}}}{{{d{Dd}}{Bl{Gj}}}{{Bn{A`Cj}}}}{{{d{Cd}}{Bl{Gj}}}{{Bn{A`Cj}}}}33{{{d{Df}}Gh}{{Bn{A`Cj}}}}3{{{d{Cd}}Al}{{Bn{A`Cj}}}}{{{d{Dd}}Gh}{{Bn{A`Cj}}}}55002{{{d{Cb}}Gh}{{Bn{A`Cj}}}}{{{d{Cd}}Gh}{{Bn{A`Cj}}}}4{{{d{Dh}}Hh}{{Bn{A`Cj}}}}{{{d{nCd}}}{{Ch{HjHl}}}}{{{d{nCn}}}{{Ch{HnI`}}}}{{EhEh}Eh}{{{d{Dd}}}{{Bn{{Bl{Cj}}Cj}}}}{{{d{Cd}}}{{Bn{{Bl{Cj}}Cj}}}}{{{d{Df}}}{{Bn{{Bl{Cj}}Cj}}}}{{{d{Dh}}}{{Bn{{Bl{Cj}}Cj}}}}{{{d{Cl}}}{{Bn{{Bl{Cj}}Cj}}}}{{{d{Cn}}}{{Bn{{Bl{Cj}}Cj}}}}{dc{}}{{{d{Dd}}}{{Bn{GhCj}}}}{{{d{Df}}}{{Bn{GhCj}}}}{c{{Bn{e}}}{}{}}0{F`{{Bn{Cb}}}}11{Fb{{Bn{Cd}}}}2{Fd{{Bn{Df}}}}{Ff{{Bn{Dh}}}}4{Fh{{Bn{ClCj}}}}5{Fj{{Bn{CnCj}}}}6{{}{{Bn{c}}}{}}0000000{{{d{Cd}}Dje}{{Bn{cCj}}}{}{{Bj{}{{Bf{{Bn{cCj}}}}}}}}{{{d{Df}}Dje}{{Bn{cCj}}}{}{{Bj{}{{Bf{{Bn{cCj}}}}}}}}{{{d{Dh}}Dje}{{Bn{cCj}}}{}{{Bj{}{{Bf{{Bn{cCj}}}}}}}}{{{d{Cn}}Dje}{{Bn{cCj}}}{}{{Bj{}{{Bf{{Bn{cCj}}}}}}}}{{{d{Df}}{d{n{Ef{Ed}}}}}{{Bn{{Ch{AjCf}}Cj}}}}{{{d{Df}}}{{Bn{CfCj}}}}{{{d{Cd}}{d{n{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Cn}}{d{n{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Cd}}{d{n{Ef{Ib}}}}}{{Bn{AjCj}}}}{{{d{Cn}}{d{n{Ef{Ib}}}}}{{Bn{AjCj}}}}{{{d{Df}}{d{n{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Dh}}{d{n{Ef{Ed}}}}}{{Bn{AjCj}}}}7{{{d{Dh}}{d{n{Ef{Ed}}}}}{{Bn{{Ch{AjD`}}Cj}}}}{{{d{Df}}{d{{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Dh}}{d{{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Df}}{d{{Ef{Ed}}}}Cf}{{Bn{AjCj}}}}{{{d{Dh}}{d{{Ef{Ed}}}}c}{{Bn{AjCj}}}{{Eb{E`}}}}{{{d{Cd}}{d{{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Cn}}{d{{Ef{Ed}}}}}{{Bn{AjCj}}}}{{{d{Cd}}{d{{Ef{Hf}}}}}{{Bn{AjCj}}}}{{{d{Cn}}{d{{Ef{Hf}}}}}{{Bn{AjCj}}}}{{{d{Cb}}}{{Bn{GhCj}}}}{{{d{Cd}}}{{Bn{GhCj}}}}{{{d{Df}}}{{Bn{GhCj}}}}{dC`}0000000{{}{{Bn{DhCj}}}}{{{d{Cd}}}{{Bn{A`Cj}}}}{{{d{Df}}}{{Bn{A`Cj}}}}{{{d{Dh}}}{{Bn{A`Cj}}}}{{{d{Cn}}}{{Bn{A`Cj}}}}{{}{{Bn{A`Cj}}}}```{{}Id}{{{d{Id}}}Bb}{d{{d{c}}}{}}0{{{d{n}}}{{d{nc}}}{}}03{{{d{Id}}}Id}{{d{d{nc}}}A`{}}{dA`}{{{d{Id}}{d{Id}}}Al}{{{d{Id}}{d{nAb}}}{{Bn{A`En}}}}{{{d{If}}{d{nAb}}}{{Bn{A`En}}}}{BbId}{cc{}}01;{{{d{Id}}{d{nc}}}A`Ih}<{{}c{}}0=={{{d{nIf}}{d{nGn}}}{{H`{{Bl{A`}}}}}}>{{{d{nIf}}}{{Bl{A`}}}}{Id{{Bn{IfCj}}}}{{}Id}{dc{}}{c{{Bn{e}}}{}{}}0{{}{{Bn{c}}}{}}0{dC`}0444``{{{d{{Bd{c}}}}}A`{}}{{{d{{Bd{c}}}}}Ij{}}{d{{d{c}}}{}}0{{{d{n}}}{{d{nc}}}{}}0{{{d{n{Bd{c}}}}}A`{}}{{{d{Il}}{d{nAb}}}{{Bn{A`En}}}}0{{{d{{Bd{c}}}}{d{nAb}}}{{Bn{A`En}}}In}{cc{}}0{{}c{}}0{{}}{Il{{Jb{J`}}}}{{{d{Il}}}Al}{{{d{{Bd{c}}}}}Al{}}1{{{Hb{{d{n{Bd{c}}}}}}{d{nGn}}}H`{}}{e{{Bd{c}}}Bh{{Bj{}{{Bf{c}}}}Bh}}{dJd}{c{{Bn{e}}}{}{}}0{{}{{Bn{c}}}{}}0{Il{{Bn{{Jb{J`}}Il}}}}{{{Hb{{d{nc}}}}{d{nGn}}}H`{}}{dC`}0{{}A`}````{{JfGj}Jf}{{{d{nJf}}Gj}A`}{d{{d{c}}}{}}000{{{d{n}}}{{d{nc}}}{}}000{{{d{Jf}}Gj}{{Bl{Jf}}}}{{{d{Jf}}Jf}{{Bl{Gj}}}}1{{{d{Jf}}}Jf}{{d{d{nc}}}A`{}}{dA`}{{{d{Jf}}{d{Jf}}}Ej}{{{d{Jh}}}Jf}{{{d{Jf}}Jf}Gj}{{{d{Jf}}}Gj}{{{d{Jf}}{d{Jf}}}Al}{{{d{Jf}}{d{nAb}}}{{Bn{A`En}}}}{{{d{Jj}}{d{nAb}}}{{Bn{A`En}}}}{{{d{{Jl{c}}}}{d{nAb}}}{{Bn{A`En}}}In}{{{d{Jh}}{d{nAb}}}{{Bn{A`En}}}}{cc{}}{JnJf}1110{{{d{n{Jl{c}}}}}{{d{nc}}}{}}{{{d{{Jl{c}}}}}{{d{c}}}{}}{{{d{Jf}}{d{nc}}}A`Ih}{GjJj}{{JfGj}Jj}{{}c{}}000{{}}0{{{Jl{c}}}c{}}{JfJn}{{{d{Jh}}}Al}{{{d{Jj}}}K`}{{}Jf}{{{d{Jf}}{d{Jf}}}{{Bl{Ej}}}}{{{d{Jj}}}Gj}{{{Hb{{d{n{Jl{c}}}}}}{d{nGn}}}H`j}{{{Hb{{d{nJh}}}}{d{nGn}}}H`}{{{d{nJj}}{d{nGn}}}{{H`{Jf}}}}{{{d{nJj}}}A`}{{{Hb{{d{nJh}}}}Jf}A`}{{{d{nJj}}Gj}A`}{{{d{nJj}}Jf}A`}3{{{d{Jf}}Jf}Gj}{{{d{nJj}}K`}A`}{GjJh}{JfJh}{{JfGj}Jf}{{JfJf}Gj}{{{d{nJf}}Gj}A`}{{{d{nJj}}}Jf}{{Gjc}JlKb}{dc{}}{c{{Bn{e}}}{}{}}000{{}{{Bn{c}}}{}}000{{{Hb{{d{nc}}}}{d{nGn}}}H`{}}{dC`}000","D":"BK`","p":[[5,"System",0,548],[1,"reference"],[5,"ArbiterHandle",0,549],[5,"Runtime",0,550],[10,"Future",551],[5,"SystemRunner",0,548],[0,"mut"],[1,"unit"],[5,"Formatter",552],[8,"Result",552],[5,"Arbiter",0,549],[5,"Runtime",553],[1,"usize"],[1,"bool"],[8,"Result",554],[8,"Result",555],[1,"i32"],[5,"JoinHandle",431,556],[17,"Output"],[10,"Send",557],[10,"FnOnce",558],[6,"Option",559],[6,"Result",560],[5,"TypeId",561],[5,"TcpListener",88,562],[5,"TcpStream",88,563],[6,"SocketAddr",564],[1,"tuple"],[5,"Error",555],[5,"UnixListener",88,565],[5,"UnixStream",88,566],[5,"SocketAddr",567],[5,"BorrowedFd",568],[5,"TcpSocket",88,569],[5,"UdpSocket",88,570],[5,"UnixDatagram",88,571],[5,"Interest",572],[10,"FnMut",558],[10,"ToSocketAddrs",573],[5,"Path",574],[10,"AsRef",575],[1,"u8"],[1,"slice"],[5,"Ready",88,576],[6,"Ordering",577],[5,"Vec",578],[5,"Error",552],[5,"TcpListener",579],[5,"TcpStream",579],[5,"UdpSocket",580],[5,"UnixDatagram",581],[5,"UnixListener",582],[5,"UnixStream",583],[5,"OwnedReadHalf",584],[5,"OwnedWriteHalf",584],[5,"OwnedReadHalf",585],[5,"OwnedWriteHalf",585],[5,"Ipv4Addr",586],[5,"Ipv6Addr",586],[1,"u32"],[5,"Duration",587],[5,"UCred",588],[5,"Context",589],[6,"Poll",590],[5,"Pin",591],[5,"ReadBuf",592],[5,"IoSlice",593],[6,"Shutdown",594],[5,"ReadHalf",595],[5,"WriteHalf",595],[5,"ReadHalf",596],[5,"WriteHalf",596],[5,"IoSliceMut",593],[5,"SignalKind",390,597],[5,"Signal",390,597],[10,"Hasher",598],[5,"AbortHandle",599],[5,"JoinError",431,600],[10,"Debug",552],[10,"Any",561],[5,"Box",601],[5,"String",602],[5,"Instant",464,603],[5,"Sleep",464,604],[5,"Interval",464,605],[5,"Timeout",464,606],[5,"Instant",607],[6,"MissedTickBehavior",605],[10,"IntoFuture",608]],"r":[[0,549],[1,549],[2,550],[3,548],[4,548],[46,609],[51,610],[66,609],[94,576],[95,562],[96,569],[97,563],[98,570],[99,571],[100,565],[101,566],[388,611],[390,597],[391,597],[419,597],[431,600],[432,556],[453,612],[463,613],[464,603],[465,605],[466,604],[467,606],[502,605],[503,605],[527,604],[528,604],[533,606]],"b":[[440,"impl-Display-for-JoinError"],[441,"impl-Debug-for-JoinError"],[529,"impl-Sub%3CDuration%3E-for-Instant"],[530,"impl-Sub-for-Instant"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAMwALAAJAA8AGwAEACMAAABFAAEASgAOAGsADQCEABIAmAADAKMACADEAAAA1AABAO4AAAD5AAEA/gABAA4BAwAUAQEAPwEAAEYBAABJAQEATAEBAE8BAABSAQAAVAEAAFYBCAB4AQcAiwEDAJABBgCbAQAApgEGALQBBwDAAQAAxQEAAMcBBADNAQIA1QEJAOIBAwDpAQQA7wEAAPYBAAD9AQEABAIAAAYCAQASAgIAFwINAA=="}],["actix_server",{"t":"PGPFFFEPFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["Disabled","MpTcp","NoFallback","Server","ServerBuilder","ServerHandle","ServerServiceFactory","TcpFallback","TestServer","backlog","bind","bind_uds","borrow","","","","","borrow_mut","","","","","build","clone","","clone_into","","clone_to_uninit","","default","disable_signals","fmt","","from","","","","","handle","into","","","","","into_future","listen","listen_uds","max_concurrent_connections","mptcp","new","pause","poll","resume","run","shutdown_timeout","start","start_with_builder","stop","system_exit","to_owned","","try_from","","","","","try_into","","","","","try_poll","type_id","","","","","unused_addr","worker_max_blocking_threads","workers"],"q":[[0,"actix_server"],[80,"actix_server::builder"],[81,"std::io::error"],[82,"core::convert"],[83,"std::net::socket_addr"],[84,"tokio::net::tcp::stream"],[85,"std::path"],[86,"tokio::net::unix::stream"],[87,"actix_server::handle"],[88,"core::fmt"],[89,"actix_server::server"],[90,"std::net::tcp"],[91,"std::os::unix::net::listener"],[92,"core::future::future"],[93,"core::pin"],[94,"core::task::wake"],[95,"core::task::poll"],[96,"core::result"],[97,"core::any"],[98,"core::net::socket_addr"],[99,"actix_server::service"],[100,"actix_server::test_server"]],"i":"Ah`0````0`b000BbCn3Aj321402404040334032140232140233333020331103403214032140232140133","f":"`````````{{bd}b}{{bceg}{{f{b}}}{{j{h}}}l{{`{n}}}}{{bceg}{{f{b}}}{{j{h}}}{{j{A`}}}{{`{Ab}}}}{Ad{{Ad{c}}}{}}0000{{{Ad{Af}}}{{Ad{Afc}}}{}}0000{{}b}{{{Ad{Ah}}}Ah}{{{Ad{Aj}}}Aj}{{Ad{Ad{Afc}}}Al{}}0{AdAl}04{bb}{{{Ad{Ah}}{Ad{AfAn}}}B`}{{{Ad{Aj}}{Ad{AfAn}}}B`}{cc{}}0000{{{Ad{Bb}}}Aj}{{}c{}}0000{{}}{{bcBde}{{f{b}}}{{j{h}}}{{`{n}}}}{{bcBfe}{{f{b}}}{{j{h}}}{{`{Ab}}}}{{bBh}b}{{bAh}b}?{{{Ad{Aj}}}{{`{{Bl{}{{Bj{Al}}}}}}}}{{{Bn{{Ad{AfBb}}}}{Ad{AfC`}}}{{Cb{c}}}{}}1{bBb}{{bCd}b}``{{{Ad{Aj}}Cf}{{`{{Bl{}{{Bj{Al}}}}}}}}?{Adc{}}0{c{{Ch{e}}}{}{}}0000{{}{{Ch{c}}}{}}0000{{{Bn{{Ad{Afc}}}}{Ad{AfC`}}}Cb{}}{AdCj}0000{{}Cl}<<","D":"Eb","p":[[5,"ServerBuilder",0,80],[1,"u32"],[8,"Result",81],[1,"str"],[10,"AsRef",82],[10,"ToSocketAddrs",83],[5,"TcpStream",84],[5,"Path",85],[5,"UnixStream",86],[1,"reference"],[0,"mut"],[6,"MpTcp",0,80],[5,"ServerHandle",0,87],[1,"unit"],[5,"Formatter",88],[8,"Result",88],[5,"Server",0,89],[5,"TcpListener",90],[5,"UnixListener",91],[1,"usize"],[17,"Output"],[10,"Future",92],[5,"Pin",93],[5,"Context",94],[6,"Poll",95],[1,"u64"],[1,"bool"],[6,"Result",96],[5,"TypeId",97],[6,"SocketAddr",98],[5,"TestServer",0]],"r":[[1,80],[3,89],[4,80],[5,87],[6,99],[8,100]],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAACcABwAHAAAADQAJABgABgAgAAEALQAAADQAAAA8ABEA"}],["actix_service",{"t":"FRRRRRRRRRKKRRRKRKKKKRKQNNNNHHHHHNNCMNNNHHHQNNMNHMNNNNHNNNNNNNNMNMMNNNNHIIFINNHNNNNHHNNN","n":["ApplyTransform","Config","Error","","","Future","","","InitError","","IntoService","IntoServiceFactory","Response","","","Service","","ServiceExt","ServiceFactory","ServiceFactoryExt","Transform","","TransformExt","always_ready","and_then","","","","apply","apply_cfg","apply_cfg_factory","apply_fn","apply_fn_factory","borrow","borrow_mut","boxed","call","clone","clone_into","clone_to_uninit","fn_factory","fn_factory_with_config","fn_service","forward_ready","from","into","into_factory","","into_service","","map","","","","map_config","map_err","","","","map_init_err","","","","new_service","","new_transform","poll_ready","to_owned","try_from","try_into","type_id","unit_config","BoxFuture","BoxService","BoxServiceFactory","RcService","borrow","borrow_mut","factory","from","into","into_factory","new_service","rc_service","service","try_from","try_into","type_id"],"q":[[0,"actix_service"],[72,"actix_service::boxed"],[88,"actix_service::ext"],[89,"actix_service::transform"],[90,"core::clone"],[91,"core::result"],[92,"core::future::future"],[93,"core::ops::function"],[94,"core::task::wake"],[95,"core::task::poll"],[96,"core::any"],[97,"actix_service::apply_cfg"],[98,"actix_service::apply"],[99,"actix_service::fn_service"],[100,"actix_service::map_config"]],"i":"`A`Aff210212``102`2````1``b0j0`````Ad0`3000````00Ab1`h4433`443333C`083763333`````Cj0`0000``000","f":"````````````````````````{{bi}{{`{bgk}}}{}{}{{f{c}{{d{e}}}}}{{h{gc}}}{}}0{{jm}{{`{jko}}}{}{}{}{}{{A`{c}{{l{e}}{d{g}}{n{i}}}}}{{Ab{kc}}}{}}0{{ei}{{Ad{egc}}}{}{{Af{c}{{n{}}}}}{{A`{c}}}{{Ab{gc}}}}{{eo}{{`{{A`{c}{{l{g}}{Ah{}}{d{}}{Aj{i}}{n{k}}{Al{m}}}}An}}}{}{{f{c}}}{}{{f{c}}}{}{{Bd{}{{B`{{Bb{ik}}}}}}}{{Bh{g{Bf{e}}}{{B`{m}}}}}}{{em}{{`{{A`{c}{{l{g}}{Ah{}}{d{}}{Aj{i}}{n{}}}}An}}}{}{{A`{c}{{l{Bj}}}}}{}{{f{c}}}{{Bd{}{{B`{{Bb{i}}}}}}}{{Bh{gBf}{{B`{k}}}}}}{{iAa}{{`{gAakcme}}}{}{}{{f{c}{{d{e}}}}}{{h{gc}}}{}{}{{Bd{}{{B`{{Bb{me}}}}}}}{{Bh{k{Bf{g}}}{{B`{o}}}}}}{{iAa}{{`{gAakcme}}}{}{}{{A`{c}{{d{e}}}}}{{Ab{gc}}}{}{}{{Bd{}{{B`{{Bb{me}}}}}}}{{Bh{kBf}{{B`{o}}}}An}}{Bf{{Bf{c}}}{}}{{{Bf{Bl}}}{{Bf{Blc}}}{}}`{{{Bf{{f{}{{Ah{c}}{d{e}}{Al{g}}}}}}i}g{}{}{{Bd{}{{B`{{Bb{ce}}}}}}}{}}{{{Bf{{Ad{ceg}}}}}{{Ad{ceg}}}{}{}{}}{{Bf{Bf{Blc}}}Bj{}}{BfBj}{k{{`{kmecig}}}{}{{f{c}}}{}{{Bd{}{{B`{{Bb{eg}}}}}}}{{Bh{}{{B`{i}}}}}{}}{m{{`{mkcgei}}}{}{}{{f{e}}}{}{{Bd{}{{B`{{Bb{gi}}}}}}}{{Bh{c}{{B`{k}}}}}}{k{{`{kicegm}}}{}{}{}{{Bd{}{{B`{{Bb{eg}}}}}}}{{Bh{c}{{B`{i}}}}An}{}}`{cc{}}{{}c{}}{Abe{}{{A`{c}}}}1{ge{}{{f{c}}}{{h{ec}}}}{he{}{{f{c}}}}{{bg}{{`{bgie}}}{}{}{{Bn{c}{{B`{e}}}}}{}}0{{jg}{{`{jgie}}}{}{}{{Bn{c}{{B`{e}}}}An}{}}0{{gk}{{`{ecki}}}{}{{A`{c}}}{{Ab{ec}}}{}{{Bh{i}{{B`{}}}}}}{{bg}{{`{bige}}}{}{}{{Bh{c}{{B`{e}}}}}{}}0{{jg}{{`{jige}}}{}{}{{Bh{c}{{B`{e}}}}An}{}}0{{jg}{{`{jgie}}}{}{}{{Bh{c}{{B`{e}}}}An}{}}0{{C`g}{{`{C`ikge}}}{}{}{{Bh{c}{{B`{e}}}}An}{}{}}0{{{Bf{{A`{}{{Ah{c}}{d{e}}{l{g}}{Aj{i}}{n{m}}{Al{o}}}}}}g}o{}{}{}{{f{k}{{Ah{c}}{d{e}}}}}{}{}{{Bd{}{{B`{{Bb{im}}}}}}}}{{{Bf{{Ad{egc}}}}}i{}{{Af{c}{{n{}}}}}{{A`{c}}}{}}{{{Bf{{Af{}{{Ah{c}}{d{e}}{Cb{g}}{n{k}}{Al{m}}}}}}o}m{}{}{{f{i}{{Ah{c}}{d{e}}}}}{}{}{{Bd{}{{B`{{Bb{gk}}}}}}}{}}{{{Bf{{f{}{{Ah{c}}{d{e}}{Al{g}}}}}}{Bf{BlCd}}}{{Cf{{Bb{Bje}}}}}{}{}{{Bd{}{{B`{{Bb{ce}}}}}}}}{Bfc{}}{c{{Bb{e}}}{}{}}{{}{{Bb{c}}}{}}{BfCh}{g{{`{eic}}}{}{{A`{c}{{l{Bj}}}}}{{Ab{ec}}}{}}````{Bf{{Bf{c}}}{}}{{{Bf{Bl}}}{{Bf{Blc}}}{}}{e{{Cj{c}}}{}{{A`{c}}}}{cc{}}{{}c{}}0{{{Bf{{Cj{cegik}}}}c}m{}{}{}{}{}{}}{e{{Cl{c}}}{}{{f{c}}}}{e{{Cn{c}}}{}{{f{c}}}};:9","D":"Hn","p":[[10,"ServiceExt",0,88],[17,"Error"],[10,"Service",0],[10,"IntoService",0],[10,"ServiceFactoryExt",0,88],[17,"Config"],[17,"InitError"],[10,"ServiceFactory",0],[10,"IntoServiceFactory",0],[5,"ApplyTransform",0,89],[10,"Transform",0,89],[17,"Response"],[17,"Service"],[17,"Future"],[10,"Clone",90],[17,"Output"],[6,"Result",91],[10,"Future",92],[1,"reference"],[10,"Fn",93],[1,"unit"],[0,"mut"],[10,"FnMut",93],[10,"TransformExt",0,88],[17,"Transform"],[5,"Context",94],[6,"Poll",95],[5,"TypeId",96],[5,"BoxServiceFactory",72],[8,"RcService",72],[8,"BoxService",72]],"r":[[0,89],[17,88],[19,88],[20,89],[22,88],[28,89],[29,97],[30,97],[31,98],[32,98],[40,99],[41,99],[42,99],[54,100],[71,100]],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAABEACAAiAAEAJgACADAAAABBAAAARAADAE0AAQBSAAEAVgACAA=="}],["actix_tls",{"t":"CCPPPGNNNNNNNHCCCCCCNNNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNFFNNNNNNNNNNNNNNNNNNNNNNNNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNTFFPGTPFFFPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNFONNNONNNNNONOOOOOONNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNFONNNONNNNNONOOOOOOONNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNFONNNNNONNNONNONOOOOOOONNNNFFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNNNFONNNNNNOOOONNNNONNNONOOOOOOOONNNNGFFFFKPPPKFPFPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNNNNNNNNNNNNNNNNMCNNNNNCNNNNNNNNCCCCNNNNNNNNCNNNNNNNNNNNNNNNNNNNNNNNNNNNNFNNNNNNNNNNNNNCNNNNFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFNNNNNNNNNNNNNNNNNNNNCNNNNNNNNNFFPGPFFFPNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNFFNNNNNNNNNNNNNNNNNHNNNCNNNNNNNNNHFFJONNNNNNONNNOOONNNNNNNNNOONNNNONNNNNNNFFNNNNNNNNNNNNNNNNNHNNNCNNNNNNNNNHFFSONNNNNNONNNOONNNNNNNNNOONNNNONNNNNNNFFNNNNNNNNNNNNNNNNNHNNNCNNNNNNNNNHFFSONNNNNNNNONNNNOOONNNNNNNNNOONNNNONNNNNNNFFNNNNNNNNNNNNNNNNNHNNNCNNNNNNNNNHFFSONNNNNNNNNOOOONNNNNOOONNNNNNNNNNNOONNNNNOONNNNNNNFFNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["accept","connect","Service","Timeout","Tls","TlsError","borrow","borrow_mut","fmt","","from","into","into_service_error","max_concurrent_tls_connect","native_tls","openssl","rustls_0_20","rustls_0_21","rustls_0_22","rustls_0_23","source","to_string","try_from","try_into","type_id","Acceptor","AcceptorService","TlsStream","borrow","","","borrow_mut","","","call","clone","clone_into","clone_to_uninit","deref","deref_mut","from","","","","into","","","into_factory","into_service","is_write_vectored","new","new_service","poll_flush","poll_read","poll_ready","poll_shutdown","poll_write","poll_write_vectored","reexports","set_handshake_timeout","to_owned","try_from","","","try_into","","","type_id","","","Error","TlsAcceptor","accept","borrow","","borrow_mut","","clone","clone_into","clone_to_uninit","fmt","","","from","","","","into","","source","to_owned","to_string","try_from","","try_into","","type_id","","Acceptor","AcceptorService","TlsStream","borrow","","","borrow_mut","","","call","clone","clone_into","clone_to_uninit","deref","deref_mut","from","","","","into","","","into_factory","into_service","is_write_vectored","new","new_service","poll_flush","poll_read","poll_ready","poll_shutdown","poll_write","poll_write_vectored","reexports","set_handshake_timeout","to_owned","try_from","","","try_into","","","type_id","","","ALERT_FATAL","AlpnError","Error","Failure","HandshakeError","NOACK","SetupFailure","Ssl","SslAcceptor","SslAcceptorBuilder","WouldBlock","accept","","as_ptr","as_ref","borrow","","","","","borrow_mut","","","","build","clone","","clone_into","","clone_to_uninit","","connect","context","deref","","deref_mut","","drop","eq","fmt","","from","","","","from_ptr","into","","","","into_context","mozilla_intermediate","mozilla_intermediate_v5","mozilla_modern","mozilla_modern_v5","new","new_ex_index","to_owned","","try_from","","","","try_into","","","","type_id","","","","Acceptor","AcceptorService","TlsStream","borrow","","","borrow_mut","","","call","clone","clone_into","clone_to_uninit","deref","deref_mut","from","","","","into","","","into_factory","into_service","is_write_vectored","new","new_service","poll_flush","poll_read","poll_ready","poll_shutdown","poll_write","poll_write_vectored","reexports","set_handshake_timeout","to_owned","try_from","","","try_into","","","type_id","","","ServerConfig","alpn_protocols","borrow","borrow_mut","builder","cert_resolver","clone","clone_into","clone_to_uninit","fmt","from","ignore_client_order","into","key_log","max_early_data_size","max_fragment_size","send_half_rtt_data","session_storage","ticketer","to_owned","try_from","try_into","type_id","Acceptor","AcceptorService","TlsStream","borrow","","","borrow_mut","","","call","clone","clone_into","clone_to_uninit","deref","deref_mut","from","","","","into","","","into_factory","into_service","is_write_vectored","new","new_service","poll_flush","poll_read","poll_ready","poll_shutdown","poll_write","poll_write_vectored","reexports","set_handshake_timeout","to_owned","try_from","","","try_into","","","type_id","","","ServerConfig","alpn_protocols","borrow","borrow_mut","builder","cert_resolver","clone","clone_into","clone_to_uninit","fmt","from","ignore_client_order","into","key_log","max_early_data_size","max_fragment_size","send_half_rtt_data","send_tls13_tickets","session_storage","ticketer","to_owned","try_from","try_into","type_id","Acceptor","AcceptorService","TlsStream","borrow","","","borrow_mut","","","call","clone","clone_into","clone_to_uninit","deref","deref_mut","from","","","","into","","","into_factory","into_service","is_write_vectored","new","new_service","poll_flush","poll_read","poll_ready","poll_shutdown","poll_write","poll_write_vectored","reexports","set_handshake_timeout","to_owned","try_from","","","try_into","","","type_id","","","ServerConfig","alpn_protocols","borrow","borrow_mut","builder","builder_with_protocol_versions","builder_with_provider","cert_resolver","clone","clone_into","clone_to_uninit","enable_secret_extraction","fmt","from","ignore_client_order","into","key_log","max_early_data_size","max_fragment_size","send_half_rtt_data","send_tls13_tickets","session_storage","ticketer","to_owned","try_from","try_into","type_id","Acceptor","AcceptorService","TlsStream","borrow","","","borrow_mut","","","call","clone","clone_into","clone_to_uninit","deref","deref_mut","from","","","","into","","","into_factory","into_service","is_write_vectored","new","new_service","poll_flush","poll_read","poll_ready","poll_shutdown","poll_write","poll_write_vectored","reexports","set_handshake_timeout","to_owned","try_from","","","try_into","","","type_id","","","ServerConfig","alpn_protocols","borrow","borrow_mut","builder","builder_with_details","builder_with_protocol_versions","builder_with_provider","cert_compression_cache","cert_compressors","cert_decompressors","cert_resolver","clone","clone_into","clone_to_uninit","crypto_provider","enable_secret_extraction","fips","fmt","from","ignore_client_order","into","key_log","max_early_data_size","max_fragment_size","send_half_rtt_data","send_tls13_tickets","session_storage","ticketer","time_provider","to_owned","try_from","try_into","type_id","ConnectError","ConnectInfo","Connection","Connector","ConnectorService","Host","InvalidInput","Io","NoRecords","Resolve","Resolver","","ResolverService","Unresolved","addrs","borrow","","","","","","","borrow_mut","","","","","","","call","","clone","","","","clone_into","","","","clone_to_uninit","","","","custom","","default","","","","deref","deref_mut","eq","fmt","","","","","from","","","","","","","","hash","hostname","","","into","","","","","","","into_factory","","into_parts","into_service","","io_mut","io_ref","lookup","native_tls","new","","","new_service","","openssl","poll_ready","","port","","","replace_io","request","","rustls_0_20","rustls_0_21","rustls_0_22","rustls_0_23","service","","set_addr","set_addrs","set_local_addr","set_port","source","take_addrs","tcp","to_owned","","","","to_string","","try_from","","","","","","","try_into","","","","","","","type_id","","","","","","","with_addr","TlsConnector","borrow","borrow_mut","call","clone","clone_into","clone_to_uninit","from","into","into_factory","into_service","new","new_service","poll_ready","reexports","to_owned","try_from","try_into","type_id","AsyncTlsStream","TlsConnector","as_raw_fd","borrow","","borrow_mut","","builder","clone","clone_into","clone_to_uninit","connect","fmt","","from","","get_mut","get_ref","into","","new","poll_flush","poll_read","poll_shutdown","poll_write","to_owned","try_from","","try_into","","type_id","","TlsConnector","TlsConnectorService","borrow","","borrow_mut","","call","clone","","clone_into","","clone_to_uninit","","from","","into","","into_factory","into_service","new","new_service","poll_ready","reexports","service","to_owned","","try_from","","try_into","","type_id","","AsyncSslStream","Error","Failure","HandshakeError","SetupFailure","SslConnector","SslConnectorBuilder","SslMethod","WouldBlock","accept","as_ptr","borrow","","","","","","borrow_mut","","","","","","build","builder","clone","","clone_into","","clone_to_uninit","","code","configure","connect","","context","deref","deref_mut","do_handshake","dtls","fmt","","","","","","from","","","","","","","","from_ptr","get_mut","get_pin_mut","get_ref","into","","","","","","into_context","into_io_error","io_error","new","peek","poll_accept","poll_connect","poll_do_handshake","poll_flush","poll_peek","poll_read","poll_read_early_data","poll_shutdown","poll_write","poll_write_early_data","read_early_data","source","","ssl","ssl_error","tls","tls_client","tls_server","to_owned","","to_string","","try_from","","","","","","try_into","","","","","","type_id","","","","","","write_early_data","TlsConnector","TlsConnectorService","borrow","","borrow_mut","","call","clone","","clone_into","","clone_to_uninit","","from","","into","","into_factory","into_service","native_roots_cert_store","new","new_service","poll_ready","reexports","service","to_owned","","try_from","","try_into","","type_id","","webpki_roots_cert_store","AsyncTlsStream","ClientConfig","TLS_SERVER_ROOTS","alpn_protocols","as_raw_fd","borrow","","borrow_mut","","builder","client_auth_cert_resolver","clone","clone_into","clone_to_uninit","enable_early_data","enable_sni","enable_tickets","fmt","","from","","get_mut","get_ref","into","","into_inner","key_log","max_fragment_size","poll_flush","poll_read","poll_shutdown","poll_write","session_storage","to_owned","try_from","","try_into","","type_id","","TlsConnector","TlsConnectorService","borrow","","borrow_mut","","call","clone","","clone_into","","clone_to_uninit","","from","","into","","into_factory","into_service","native_roots_cert_store","new","new_service","poll_ready","reexports","service","to_owned","","try_from","","try_into","","type_id","","webpki_roots_cert_store","AsyncTlsStream","ClientConfig","TLS_SERVER_ROOTS","alpn_protocols","as_raw_fd","borrow","","borrow_mut","","builder","client_auth_cert_resolver","clone","clone_into","clone_to_uninit","enable_early_data","enable_sni","fmt","","from","","get_mut","get_ref","into","","into_inner","key_log","max_fragment_size","poll_flush","poll_read","poll_shutdown","poll_write","resumption","to_owned","try_from","","try_into","","type_id","","TlsConnector","TlsConnectorService","borrow","","borrow_mut","","call","clone","","clone_into","","clone_to_uninit","","from","","into","","into_factory","into_service","native_roots_cert_store","new","new_service","poll_ready","reexports","service","to_owned","","try_from","","try_into","","type_id","","webpki_roots_cert_store","AsyncTlsStream","ClientConfig","TLS_SERVER_ROOTS","alpn_protocols","as_raw_fd","borrow","","borrow_mut","","builder","builder_with_protocol_versions","builder_with_provider","client_auth_cert_resolver","clone","clone_into","clone_to_uninit","dangerous","enable_early_data","enable_secret_extraction","enable_sni","fmt","","from","","get_mut","get_ref","into","","into_inner","key_log","max_fragment_size","poll_flush","poll_read","poll_shutdown","poll_write","resumption","to_owned","try_from","","try_into","","type_id","","TlsConnector","TlsConnectorService","borrow","","borrow_mut","","call","clone","","clone_into","","clone_to_uninit","","from","","into","","into_factory","into_service","native_roots_cert_store","new","new_service","poll_ready","reexports","service","to_owned","","try_from","","try_into","","type_id","","webpki_roots_cert_store","AsyncTlsStream","ClientConfig","TLS_SERVER_ROOTS","alpn_protocols","as_raw_fd","borrow","","borrow_mut","","builder","builder_with_details","builder_with_protocol_versions","builder_with_provider","cert_compression_cache","cert_compressors","cert_decompressors","client_auth_cert_resolver","clone","clone_into","clone_to_uninit","crypto_provider","dangerous","enable_early_data","enable_secret_extraction","enable_sni","fips","fmt","","from","","get_mut","get_ref","into","","into_inner","is_write_vectored","key_log","max_fragment_size","poll_flush","poll_read","poll_shutdown","poll_write","poll_write_vectored","resumption","time_provider","to_owned","try_from","","try_into","","type_id","","TcpConnector","TcpConnectorService","borrow","","borrow_mut","","call","clone","","clone_into","","clone_to_uninit","","default","","fmt","","from","","into","","into_factory","into_service","new_service","poll_ready","service","to_owned","","try_from","","try_into","","type_id",""],"q":[[0,"actix_tls"],[2,"actix_tls::accept"],[25,"actix_tls::accept::native_tls"],[70,"actix_tls::accept::native_tls::reexports"],[98,"actix_tls::accept::openssl"],[143,"actix_tls::accept::openssl::reexports"],[214,"actix_tls::accept::rustls_0_20"],[259,"actix_tls::accept::rustls_0_20::reexports"],[282,"actix_tls::accept::rustls_0_21"],[327,"actix_tls::accept::rustls_0_21::reexports"],[351,"actix_tls::accept::rustls_0_22"],[396,"actix_tls::accept::rustls_0_22::reexports"],[423,"actix_tls::accept::rustls_0_23"],[468,"actix_tls::accept::rustls_0_23::reexports"],[502,"actix_tls::connect"],[642,"actix_tls::connect::native_tls"],[661,"actix_tls::connect::native_tls::reexports"],[693,"actix_tls::connect::openssl"],[725,"actix_tls::connect::openssl::reexports"],[835,"actix_tls::connect::rustls_0_20"],[869,"actix_tls::connect::rustls_0_20::reexports"],[909,"actix_tls::connect::rustls_0_21"],[943,"actix_tls::connect::rustls_0_21::reexports"],[982,"actix_tls::connect::rustls_0_22"],[1016,"actix_tls::connect::rustls_0_22::reexports"],[1059,"actix_tls::connect::rustls_0_23"],[1093,"actix_tls::connect::rustls_0_23::reexports"],[1145,"actix_tls::connect::tcp"],[1179,"core::fmt"],[1180,"core::convert"],[1181,"core::error"],[1182,"core::option"],[1183,"alloc::string"],[1184,"core::result"],[1185,"core::any"],[1186,"actix_rt::net"],[1187,"tokio_native_tls"],[1188,"core::pin"],[1189,"core::task::wake"],[1190,"std::io::error"],[1191,"core::task::poll"],[1192,"tokio::io::read_buf"],[1193,"std::io"],[1194,"core::time"],[1195,"native_tls"],[1196,"tokio::io::async_read"],[1197,"tokio::io::async_write"],[1198,"core::marker"],[1199,"native_tls::imp"],[1200,"openssl::ssl::connector"],[1201,"openssl::ssl"],[1202,"openssl::ssl::error"],[1203,"openssl_sys::openssl::handwritten::types"],[1204,"openssl::error"],[1205,"openssl::ex_data"],[1206,"tokio_rustls::server"],[1207,"rustls::server::server_conn"],[1208,"rustls::builder"],[1209,"rustls::versions"],[1210,"rustls::crypto"],[1211,"alloc::sync"],[1212,"rustls::time_provider"],[1213,"actix_tls::connect::info"],[1214,"core::net::socket_addr"],[1215,"core::iter::traits::iterator"],[1216,"core::iter::traits::exact_size"],[1217,"core::iter::traits::marker"],[1218,"core::clone"],[1219,"actix_tls::connect::host"],[1220,"actix_tls::connect::connector"],[1221,"actix_tls::connect::resolver"],[1222,"actix_tls::connect::resolve"],[1223,"actix_tls::connect::connection"],[1224,"core::cmp"],[1225,"actix_tls::connect::error"],[1226,"core::hash"],[1227,"alloc::vec"],[1228,"alloc::boxed"],[1229,"futures_core::future"],[1230,"core::iter::traits::collect"],[1231,"core::net::ip_addr"],[1232,"std::os::fd::raw"],[1233,"openssl_sys::openssl::handwritten::ssl"],[1234,"rustls::anchors"],[1235,"rustls::client::client_conn"],[1236,"rustls::webpki::anchors"],[1237,"rustls::client::client_conn::danger"],[1238,"rustls::client::client_conn::connection"],[1239,"webpki_roots"]],"i":"``f00`0000000```````00000```BdBbAn210011122221021010211220222`11210210210``BjCn101111001001101010010101```E`DnDl210011122221021010211220222`11210210210Ff``Eh`10```0EdEn00Fd2411024102424241201011441024110241222221124024102410241```GlGjGh210011122221021010211220222`11210210210`H`000000000000000000000```HjHhHf210011122221021010211220222`11210210210`Hn0000000000000000000000```IhIfId210011122221021010211220222`11210210210`Il0000000000000000000000000```JnJlJj210011122221021010211220222`11210210210`Kb00000000000000000000000000000000``````Mn00``0`0L`MjMdM`43MfMb43265102032103210321010321044546655432655105Ln5654376214253155Mh`65753`42117667````53777787`5432876548732654873265487327`Of000000000000`0000``Bf0Oh100000010101110011110101010``A@jA@h100101010101010110`110101010``Eh`0```0EbFn1AAbA@lA@n53421053211313130141122434100554210055334444210531004444444444444054033313054210534210534210534``AAjAAh100101010101010`110`110101010````AAnAB`01011111111101010001011000011010101``ABfABd100101010101010`110`110101010````ABjABl0101111111101010001011000011010101``ACbAC`100101010101010`110`110101010````ACfACh01011111111111101010001011000011010101``AD`ACn100101010101010`110`110101010````ADdADf01011111111111111111101010001001100000111010101``ADnADl100101010101010101010110101010","f":"``````{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{{b{{f{ce}}}}{b{dh}}}jll}{{{b{{f{ce}}}}{b{dh}}}j{}{}}{cc{}}{{}c{}}{{{f{cn}}}{{f{ce}}}{}{}}{A`Ab}``````{{{b{{f{ce}}}}}{{Af{{b{Ad}}}}}AdAd}{bAh}{c{{Aj{e}}}{}{}}{{}{{Aj{c}}}{}}{bAl}```<<<;;;{{{b{An}}c}eB`{}}{{{b{Bb}}}Bb}{{b{b{dc}}}Ab{}}{bAb}{{{b{{Bd{c}}}}}{{b{e}}}{}{}}{{{b{d{Bd{c}}}}}{{b{de}}}{}{}}{{{Bf{c}}}{{Bd{c}}}{}}???>>>>>{{{b{{Bd{c}}}}}BhB`}{BjBb}{{{b{Bb}}Ab}c{}}{{{Bl{{b{d{Bd{c}}}}}}{b{dBn}}}{{Cb{{C`{Ab}}}}}B`}{{{Bl{{b{d{Bd{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{C`{Ab}}}}}B`}{{{b{An}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}2{{{Bl{{b{d{Bd{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{C`{A`}}}}}B`}{{{Bl{{b{d{Bd{c}}}}}}{b{dBn}}{b{{Ch{Cj}}}}}{{Cb{{C`{A`}}}}}B`}`{{{b{dBb}}Cl}{{b{dBb}}}}{bc{}}{c{{Aj{e}}}{}{}}00{{}{{Aj{c}}}{}}00{bAl}00``{{{b{Bj}}c}{{Aj{{Bf{c}}Cn}}}{D`DbDd}}{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{Bj}}}Bj}{{b{b{dc}}}Ab{}}{bAb}{{{b{Cn}}{b{dh}}}{{Aj{AbDf}}}}0{{{b{Bj}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}{DhCn}{DjBj}2{{}c{}}0{{{b{Cn}}}{{Af{{b{Ad}}}}}}{bc{}}{bAh}{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0```{b{{b{c}}}{}}00{{{b{d}}}{{b{dc}}}{}}00{{{b{Dl}}c}eB`{}}{{{b{Dn}}}Dn}{{b{b{dc}}}Ab{}}{bAb}{{{b{{E`{c}}}}}{{b{e}}}{}{}}{{{b{d{E`{c}}}}}{{b{de}}}{}{}}{{{Eb{c}}}{{E`{c}}}{}}{cc{}}00{{}c{}}0000{{{b{{E`{c}}}}}BhB`}{EdDn}{{{b{Dn}}Ab}c{}}{{{Bl{{b{d{E`{c}}}}}}{b{dBn}}}{{Cb{{C`{Ab}}}}}B`}{{{Bl{{b{d{E`{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{C`{Ab}}}}}B`}{{{b{Dl}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}2{{{Bl{{b{d{E`{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{C`{A`}}}}}B`}{{{Bl{{b{d{E`{c}}}}}}{b{dBn}}{b{{Ch{Cj}}}}}{{Cb{{C`{A`}}}}}B`}`{{{b{dDn}}Cl}{{b{dDn}}}}{bc{}}{c{{Aj{e}}}{}{}}00{{}{{Aj{c}}}{}}00{bAl}00```````````{{{b{Ed}}c}{{Aj{{Ef{c}}{Eh{c}}}}}{EjEl}}{{Enc}{{Aj{{Ef{c}}{Eh{c}}}}}{EjEl}}{{{b{En}}}F`}{{{b{En}}}{{b{Fb}}}}{b{{b{c}}}{}}0010{{{b{d}}}{{b{dc}}}{}}000{FdEd}{{{b{Ed}}}Ed}{{{b{Ff}}}Ff}{{b{b{dc}}}Ab{}}0{bAb}09{{{b{Ed}}}{{b{Fh}}}}{{{b{Fd}}}{{b{Fj}}}}9{{{b{dFd}}}{{b{dFj}}}}{{{b{dEn}}}{{b{dFb}}}}{{{b{dEn}}}Ab}{{{b{Ff}}{b{Ff}}}Bh}{{{b{Ff}}{b{dh}}}{{Aj{AbDf}}}}{{{b{En}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}000{F`En}{{}c{}}000{EdFl}{Fn{{Aj{FdG`}}}}000{{{b{Fh}}}{{Aj{EnG`}}}}{{}{{Aj{{Gb{Enc}}G`}}}{GdGf}}{bc{}}0{c{{Aj{e}}}{}{}}000{{}{{Aj{c}}}{}}000{bAl}000```{b{{b{c}}}{}}00{{{b{d}}}{{b{dc}}}{}}00{{{b{Gh}}c}eB`{}}{{{b{Gj}}}Gj}{{b{b{dc}}}Ab{}}{bAb}{{{b{{Gl{c}}}}}{{b{e}}}{}{}}{{{b{d{Gl{c}}}}}{{b{de}}}{}{}}{{{Gn{c}}}{{Gl{c}}}{}}{cc{}}00{{}c{}}0000{{{b{{Gl{c}}}}}BhB`}{H`Gj}{{{b{Gj}}Ab}c{}}{{{Bl{{b{d{Gl{c}}}}}}{b{dBn}}}{{Cb{{C`{Ab}}}}}B`}{{{Bl{{b{d{Gl{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{C`{Ab}}}}}B`}{{{b{Gh}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}2{{{Bl{{b{d{Gl{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{C`{A`}}}}}B`}{{{Bl{{b{d{Gl{c}}}}}}{b{dBn}}{b{{Ch{Cj}}}}}{{Cb{{C`{A`}}}}}B`}`{{{b{dGj}}Cl}{{b{dGj}}}}{bc{}}{c{{Aj{e}}}{}{}}00{{}{{Aj{c}}}{}}00{bAl}00``{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{}{{Hd{H`Hb}}}}`{{{b{H`}}}H`}{{b{b{dc}}}Ab{}}{bAb}{{{b{H`}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}`{{}c{}}``````<;:9```888777{{{b{Hf}}c}eB`{}}{{{b{Hh}}}Hh}65{{{b{{Hj{c}}}}}{{b{e}}}{}{}}{{{b{d{Hj{c}}}}}{{b{de}}}{}{}}{{{Hl{c}}}{{Hj{c}}}{}}66655555{{{b{{Hj{c}}}}}BhB`}{HnHh}{{{b{Hh}}Ab}c{}}{{{Bl{{b{d{Hj{c}}}}}}{b{dBn}}}{{Cb{{C`{Ab}}}}}B`}{{{Bl{{b{d{Hj{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{C`{Ab}}}}}B`}{{{b{Hf}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}2{{{Bl{{b{d{Hj{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{C`{A`}}}}}B`}{{{Bl{{b{d{Hj{c}}}}}}{b{dBn}}{b{{Ch{Cj}}}}}{{Cb{{C`{A`}}}}}B`}`{{{b{dHh}}Cl}{{b{dHh}}}}{bc{}}{c{{Aj{e}}}{}{}}00{{}{{Aj{c}}}{}}00{bAl}00``{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{}{{Ib{HnI`}}}}`{{{b{Hn}}}Hn}{{b{b{dc}}}Ab{}}{bAb}{{{b{Hn}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}`{{}c{}}```````<;:9```888777{{{b{Id}}c}eB`{}}{{{b{If}}}If}65{{{b{{Ih{c}}}}}{{b{e}}}{}{}}{{{b{d{Ih{c}}}}}{{b{de}}}{}{}}{{{Ij{c}}}{{Ih{c}}}{}}66655555{{{b{{Ih{c}}}}}BhB`}{IlIf}{{{b{If}}Ab}c{}}{{{Bl{{b{d{Ih{c}}}}}}{b{dBn}}}{{Cb{{C`{Ab}}}}}B`}{{{Bl{{b{d{Ih{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{C`{Ab}}}}}B`}{{{b{Id}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}2{{{Bl{{b{d{Ih{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{C`{A`}}}}}B`}{{{Bl{{b{d{Ih{c}}}}}}{b{dBn}}{b{{Ch{Cj}}}}}{{Cb{{C`{A`}}}}}B`}`{{{b{dIf}}Cl}{{b{dIf}}}}{bc{}}{c{{Aj{e}}}{}{}}00{{}{{Aj{c}}}{}}00{bAl}00``{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{}{{J`{IlIn}}}}{{{b{{Ch{{b{Jb}}}}}}}{{J`{IlIn}}}}{{{Jf{Jd}}}{{J`{IlJh}}}}`{{{b{Il}}}Il}{{b{b{dc}}}Ab{}}{bAb}`{{{b{Il}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}`{{}c{}}```````>=<;```:::999{{{b{Jj}}c}eB`{}}{{{b{Jl}}}Jl}65{{{b{{Jn{c}}}}}{{b{e}}}{}{}}{{{b{d{Jn{c}}}}}{{b{de}}}{}{}}{{{K`{c}}}{{Jn{c}}}{}}66655555{{{b{{Jn{c}}}}}BhB`}{KbJl}{{{b{Jl}}Ab}c{}}{{{Bl{{b{d{Jn{c}}}}}}{b{dBn}}}{{Cb{{C`{Ab}}}}}B`}{{{Bl{{b{d{Jn{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{C`{Ab}}}}}B`}{{{b{Jj}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}2{{{Bl{{b{d{Jn{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{C`{A`}}}}}B`}{{{Bl{{b{d{Jn{c}}}}}}{b{dBn}}{b{{Ch{Cj}}}}}{{Cb{{C`{A`}}}}}B`}`{{{b{dJl}}Cl}{{b{dJl}}}}{bc{}}{c{{Aj{e}}}{}{}}00{{}{{Aj{c}}}{}}00{bAl}00``{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{}{{Kf{KbKd}}}}{{{Jf{Kh}}{Jf{Kj}}}{{Kf{KbKl}}}}{{{b{{Ch{{b{Kn}}}}}}}{{Kf{KbKd}}}}{{{Jf{Kh}}}{{Kf{KbKl}}}}````{{{b{Kb}}}Kb}{{b{b{dc}}}Ab{}}{bAb}{{{b{Kb}}}{{b{{Jf{Kh}}}}}}`{{{b{Kb}}}Bh}{{{b{Kb}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}`{{}c{}}````````{bc{}}{c{{Aj{e}}}{}{}}{{}{{Aj{c}}}{}}{bAl}``````````````{{{b{{L`{c}}}}}{{`{{Lf{}{{Lb{Ld}}}}LhLjLll}}}Ln}{b{{b{c}}}{}}000000{{{b{d}}}{{b{dc}}}{}}000000{{{b{M`}}{L`{c}}}eLn{}}{{{b{Mb}}{L`{c}}}eLn{}}{{{b{Md}}}Md}{{{b{M`}}}M`}{{{b{Mf}}}Mf}{{{b{Mb}}}Mb}{{b{b{dc}}}Ab{}}000{bAb}000{cMfMh}{cMbMh}{{}Md}{{}M`}{{}Mf}{{}Mb}{{{b{{Mj{ce}}}}}{{b{g}}}{}{}{}}{{{b{d{Mj{ce}}}}}{{b{dg}}}{}{}{}}{{{b{{L`{c}}}}{b{{L`{c}}}}}BhMl}{{{b{{Mj{ce}}}}{b{dh}}}jll}{{{b{Mn}}{b{dh}}}j}0{{{b{{L`{c}}}}{b{dh}}}jl}{{{b{{L`{c}}}}{b{dh}}}jLn}{cc{}}000{c{{L`{c}}}Ln}111{{{b{{L`{c}}}}{b{de}}}AbN`Nb}{{{b{Ln}}}{{b{Nd}}}}{{{b{{Mj{ce}}}}}{{b{Nd}}}Ln{}}{{{b{{L`{c}}}}}{{b{Nd}}}Ln}{{}c{}}00000000{{{Mj{ce}}}{{Nf{ec}}}{}{}}11{{{b{d{Mj{ce}}}}}{{b{de}}}{}{}}{{{b{{Mj{ce}}}}}{{b{e}}}{}{}}{{{b{Mh}}{b{Nd}}Nh}{{Nn{{Aj{{Nj{Ld}}{Nl{Ad}}}}}}}}`{{ce}{{Mj{ce}}}{}{}}{MfMd};{{{b{Md}}Ab}c{}}{{{b{Mf}}Ab}c{}}`{{{b{M`}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}{{{b{Mb}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}{{{b{Ln}}}{{Af{Nh}}}}0{{{b{{L`{c}}}}}NhLn}{{{Mj{ce}}g}{{Nf{e{Mj{cg}}}}}{}{}{}}{{{b{{Mj{ce}}}}}{{b{c}}}{}{}}{{{b{{L`{c}}}}}{{b{c}}}Ln}````{{{b{Md}}}M`}{{{b{Mf}}}Mb}{{{L`{c}}e}{{L`{c}}}Ln{{O`{{Af{Ld}}}}}}{{{L`{c}}e}{{L`{c}}}Ln{{Ob{}{{Lb{Ld}}}}}}{{{L`{c}}e}{{L`{c}}}Ln{{O`{Od}}}}{{{L`{c}}Nh}{{L`{c}}}Ln}{{{b{Mn}}}{{Af{{b{Ad}}}}}}{{{b{d{L`{c}}}}}{{`{{Lf{}{{Lb{Ld}}}}LhLjLll}}}Ln}`{bc{}}000{bAh}0{c{{Aj{e}}}{}{}}000000{{}{{Aj{c}}}{}}000000{bAl}000000{{cLd}{{L`{c}}}Ln}`{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{{b{Of}}{Mj{ce}}}gLnB`{}}{{{b{Of}}}Of}{{b{b{dc}}}Ab{}}{bAb}{cc{}}{{}c{}}00{OhOf}{{{b{Of}}Ab}c{}}{{{b{Of}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}`{bc{}}?>=``{{{b{{Bf{c}}}}}OjOl}<<;;{{}On}{{{b{Oh}}}Oh}:9{{{b{Oh}}{b{Nd}}c}{{Aj{{A@`{c}}{A@b{c}}}}}{EjEl}}{{{b{{Bf{c}}}}{b{dh}}}{{Aj{AbDf}}}l}{{{b{Oh}}{b{dh}}}{{Aj{AbDf}}}};;{{{b{d{Bf{c}}}}}{{b{d{A@`{{A@d{c}}}}}}}{}}{{{b{{Bf{c}}}}}{{b{{A@`{{A@d{c}}}}}}}{}}<<{{}{{Aj{OhCn}}}}{{{Bl{{b{d{Bf{c}}}}}}{b{dBn}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}{{{Bl{{b{d{Bf{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}1{{{Bl{{b{d{Bf{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{Aj{A`A@f}}}}}{D`DbDd}}<{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{A@h}}{Mj{ce}}}gLnB`{}}{{{b{A@j}}}A@j}{{{b{A@h}}}A@h}{{b{b{dc}}}Ab{}}0{bAb}0{cc{}}0{{}c{}}000{A@lA@j}{{{b{A@j}}Ab}c{}}{{{b{A@h}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}`{A@lA@h}{bc{}}0{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0`````````{{{Bl{{b{d{Eb{c}}}}}}}{{Aj{AbA@n}}}{D`Db}}{{{b{Fn}}}AA`}{b{{b{c}}}{}}00000{{{b{d}}}{{b{dc}}}{}}00000{AAbA@l}{Fn{{Aj{AAbG`}}}}{{{b{A@l}}}A@l}{{{b{Fn}}}Fn}{{b{b{dc}}}Ab{}}0{bAb}0{{{b{A@n}}}AAd}{{{b{A@l}}}{{Aj{AAfG`}}}};{{{b{A@l}}{b{Nd}}c}{{Aj{{Ef{c}}{Eh{c}}}}}{EjEl}}{{{b{A@l}}}{{b{Fh}}}}{{{b{AAb}}}{{b{Fj}}}}{{{b{dAAb}}}{{b{dFj}}}}?{{}Fn}{{{b{{Eb{c}}}}{b{dh}}}{{Aj{AbDf}}}l}{{{b{A@l}}{b{dh}}}{{Aj{AbDf}}}}{{{b{A@n}}{b{dh}}}{{Aj{AbDf}}}}0{{{b{{Eh{c}}}}{b{dh}}}{{Aj{AbDf}}}l}0{cc{}}00{G`A@n}1{G`{{Eh{c}}}{}}22{AA`Fn}{{{b{d{Eb{c}}}}}{{b{dc}}}{}}{{{Bl{{b{d{Eb{c}}}}}}}{{Bl{{b{dc}}}}}{}}{{{b{{Eb{c}}}}}{{b{c}}}{}}{{}c{}}00000{A@lFl}{A@n{{Aj{A@fA@n}}}}{{{b{A@n}}}{{Af{{b{A@f}}}}}}{{Enc}{{Aj{{Eb{c}}G`}}}{D`Db}}{{{Bl{{b{d{Eb{c}}}}}}{b{d{Ch{Cf}}}}}{{Aj{A`A@n}}}{D`Db}}{{{Bl{{b{d{Eb{c}}}}}}{b{dBn}}}{{Cb{{Aj{AbA@n}}}}}{D`Db}}00{{{Bl{{b{d{Eb{c}}}}}}{b{dBn}}}{{Cb{{Aj{AbA@f}}}}}{D`Db}}{{{Bl{{b{d{Eb{c}}}}}}{b{dBn}}{b{d{Ch{Cf}}}}}{{Cb{{Aj{A`A@n}}}}}{D`Db}}{{{Bl{{b{d{Eb{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{Aj{AbA@f}}}}}{D`Db}}12{{{Bl{{b{d{Eb{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{Aj{A`A@f}}}}}{D`Db}}{{{Bl{{b{d{Eb{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{Aj{A`A@n}}}}}{D`Db}}6{{{b{A@n}}}{{Af{{b{Ad}}}}}}{{{b{{Eh{c}}}}}{{Af{{b{Ad}}}}}l}{{{b{{Eb{c}}}}}{{b{Fb}}}{}}{{{b{A@n}}}{{Af{{b{G`}}}}}}{{}Fn}00{bc{}}0{bAh}0{c{{Aj{e}}}{}{}}00000{{}{{Aj{c}}}{}}00000{bAl}00000{{{Bl{{b{d{Eb{c}}}}}}{b{{Ch{Cf}}}}}{{Aj{A`A@n}}}{D`Db}}``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{AAh}}{Mj{ce}}}gLnB`{}}{{{b{AAj}}}AAj}{{{b{AAh}}}AAh}{{b{b{dc}}}Ab{}}0{bAb}0{cc{}}0{{}c{}}000{{}{{C`{AAl}}}}{{{Jf{AAn}}}AAj}{{{b{AAj}}Ab}c{}}{{{b{AAh}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}`{{{Jf{AAn}}}AAh}{bc{}}0{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0{{}AAl}````{{{b{{AB`{c}}}}}OjOl}{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{}{{Hd{AAnHb}}}}`{{{b{AAn}}}AAn}{{b{b{dc}}}Ab{}}{bAb}```{{{b{{AB`{c}}}}{b{dh}}}{{Aj{AbDf}}}l}{{{b{AAn}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}0{{{b{d{AB`{c}}}}}{{Nf{{b{dc}}{b{dABb}}}}}{}}{{{b{{AB`{c}}}}}{{Nf{{b{c}}{b{ABb}}}}}{}}{{}c{}}0{{{AB`{c}}}{{Nf{cABb}}}{}}``{{{Bl{{b{d{AB`{c}}}}}}{b{dBn}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}{{{Bl{{b{d{AB`{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}1{{{Bl{{b{d{AB`{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{Aj{A`A@f}}}}}{D`DbDd}}`{bc{}}{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{ABd}}{Mj{ce}}}gLnB`{}}{{{b{ABf}}}ABf}{{{b{ABd}}}ABd}{{b{b{dc}}}Ab{}}0{bAb}0{cc{}}0{{}c{}}000{{}{{C`{ABh}}}}{{{Jf{ABj}}}ABf}{{{b{ABf}}Ab}c{}}{{{b{ABd}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}`{{{Jf{ABj}}}ABd}{bc{}}0{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0{{}ABh}````{{{b{{ABl{c}}}}}OjOl}{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{}{{Ib{ABjI`}}}}`{{{b{ABj}}}ABj}{{b{b{dc}}}Ab{}}{bAb}``{{{b{{ABl{c}}}}{b{dh}}}{{Aj{AbDf}}}l}{{{b{ABj}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}0{{{b{d{ABl{c}}}}}{{Nf{{b{dc}}{b{dABn}}}}}{}}{{{b{{ABl{c}}}}}{{Nf{{b{c}}{b{ABn}}}}}{}}{{}c{}}0{{{ABl{c}}}{{Nf{cABn}}}{}}``{{{Bl{{b{d{ABl{c}}}}}}{b{dBn}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}{{{Bl{{b{d{ABl{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}1{{{Bl{{b{d{ABl{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{Aj{A`A@f}}}}}{D`DbDd}}`{bc{}}{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{AC`}}{Mj{ce}}}gLnB`{}}{{{b{ACb}}}ACb}{{{b{AC`}}}AC`}{{b{b{dc}}}Ab{}}0{bAb}0{cc{}}0{{}c{}}000{{}{{C`{ACd}}}}{{{Jf{ACf}}}ACb}{{{b{ACb}}Ab}c{}}{{{b{AC`}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}`{{{Jf{ACf}}}AC`}{bc{}}0{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0{{}ACd}````{{{b{{ACh{c}}}}}OjOl}{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{}{{J`{ACfIn}}}}{{{b{{Ch{{b{Jb}}}}}}}{{J`{ACfIn}}}}{{{Jf{Jd}}}{{J`{ACfJh}}}}`{{{b{ACf}}}ACf}{{b{b{dc}}}Ab{}}{bAb}{{{b{dACf}}}ACj}```{{{b{{ACh{c}}}}{b{dh}}}{{Aj{AbDf}}}l}{{{b{ACf}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}0{{{b{d{ACh{c}}}}}{{Nf{{b{dc}}{b{dACl}}}}}{}}{{{b{{ACh{c}}}}}{{Nf{{b{c}}{b{ACl}}}}}{}}{{}c{}}0{{{ACh{c}}}{{Nf{cACl}}}{}}``{{{Bl{{b{d{ACh{c}}}}}}{b{dBn}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}{{{Bl{{b{d{ACh{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}1{{{Bl{{b{d{ACh{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{Aj{A`A@f}}}}}{D`DbDd}}`{bc{}}{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{ACn}}{Mj{ce}}}gLnB`{}}{{{b{AD`}}}AD`}{{{b{ACn}}}ACn}{{b{b{dc}}}Ab{}}0{bAb}0{cc{}}0{{}c{}}000{{}{{C`{ADb}}}}{{{Jf{ADd}}}AD`}{{{b{AD`}}Ab}c{}}{{{b{ACn}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}`{{{Jf{ADd}}}ACn}{bc{}}0{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0{{}ADb}````{{{b{{ADf{c}}}}}OjOl}{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{}{{Kf{ADdKd}}}}{{{Jf{Kh}}{Jf{Kj}}}{{Kf{ADdKl}}}}{{{b{{Ch{{b{Kn}}}}}}}{{Kf{ADdKd}}}}{{{Jf{Kh}}}{{Kf{ADdKl}}}}````{{{b{ADd}}}ADd}{{b{b{dc}}}Ab{}}{bAb}{{{b{ADd}}}{{b{{Jf{Kh}}}}}}{{{b{dADd}}}ADh}```{{{b{ADd}}}Bh}{{{b{{ADf{c}}}}{b{dh}}}{{Aj{AbDf}}}l}{{{b{ADd}}{b{dh}}}{{Aj{AbDf}}}}{cc{}}0{{{b{d{ADf{c}}}}}{{Nf{{b{dc}}{b{dADj}}}}}{}}{{{b{{ADf{c}}}}}{{Nf{{b{c}}{b{ADj}}}}}{}}{{}c{}}0{{{ADf{c}}}{{Nf{cADj}}}{}}{{{b{{ADf{c}}}}}Bh{D`DbDd}}``{{{Bl{{b{d{ADf{c}}}}}}{b{dBn}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}{{{Bl{{b{d{ADf{c}}}}}}{b{dBn}}{b{dCd}}}{{Cb{{Aj{AbA@f}}}}}{D`DbDd}}1{{{Bl{{b{d{ADf{c}}}}}}{b{dBn}}{b{{Ch{Cf}}}}}{{Cb{{Aj{A`A@f}}}}}{D`DbDd}}{{{Bl{{b{d{ADf{c}}}}}}{b{dBn}}{b{{Ch{Cj}}}}}{{Cb{{Aj{A`A@f}}}}}{D`DbDd}}``{bc{}}{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{ADl}}{L`{c}}}eLn{}}{{{b{ADn}}}ADn}{{{b{ADl}}}ADl}{{b{b{dc}}}Ab{}}0{bAb}0{{}ADn}{{}ADl}{{{b{ADn}}{b{dh}}}j}{{{b{ADl}}{b{dh}}}j}{cc{}}0{{}c{}}000{{{b{ADn}}Ab}c{}}{{{b{ADl}}{b{dBn}}}{{Cb{{Aj{Abc}}}}}{}}{{{b{ADn}}}ADl}{bc{}}0{c{{Aj{e}}}{}{}}0{{}{{Aj{c}}}{}}0{bAl}0","D":"CIh","p":[[1,"reference"],[0,"mut"],[6,"TlsError",2],[5,"Formatter",1179],[8,"Result",1179],[10,"Debug",1179],[6,"Infallible",1180],[1,"usize"],[1,"unit"],[10,"Error",1181],[6,"Option",1182],[5,"String",1183],[6,"Result",1184],[5,"TypeId",1185],[5,"AcceptorService",25],[10,"ActixStream",1186],[5,"Acceptor",25],[5,"TlsStream",25],[5,"AsyncTlsStream",661],[1,"bool"],[5,"TlsAcceptor",70,1187],[5,"Pin",1188],[5,"Context",1189],[8,"Result",1190],[6,"Poll",1191],[5,"ReadBuf",1192],[1,"u8"],[1,"slice"],[5,"IoSlice",1193],[5,"Duration",1194],[5,"Error",70,1195],[10,"AsyncRead",1196],[10,"AsyncWrite",1197],[10,"Unpin",1198],[5,"Error",1179],[6,"Error",1199],[5,"TlsAcceptor",1195],[5,"AcceptorService",98],[5,"Acceptor",98],[5,"TlsStream",98],[5,"AsyncSslStream",725],[5,"SslAcceptor",143,1200],[5,"SslStream",1201],[6,"HandshakeError",725,1202],[10,"Read",1193],[10,"Write",1193],[5,"Ssl",143,1201],[6,"SSL",1203],[5,"SslRef",1201],[5,"SslAcceptorBuilder",143,1200],[5,"AlpnError",143,1201],[5,"SslContextRef",1201],[5,"SslContextBuilder",1201],[5,"SslContext",1201],[5,"SslMethod",725,1201],[5,"ErrorStack",1204],[5,"Index",1205],[10,"Sync",1198],[10,"Send",1198],[5,"AcceptorService",214],[5,"Acceptor",214],[5,"TlsStream",214],[5,"TlsStream",1206],[5,"ServerConfig",259,1207],[5,"WantsCipherSuites",1208],[5,"ConfigBuilder",1208],[5,"AcceptorService",282],[5,"Acceptor",282],[5,"TlsStream",282],[5,"TlsStream",1206],[5,"ServerConfig",327,1207],[5,"WantsCipherSuites",1208],[5,"ConfigBuilder",1208],[5,"AcceptorService",351],[5,"Acceptor",351],[5,"TlsStream",351],[5,"TlsStream",1206],[5,"ServerConfig",396,1207],[5,"WantsVerifier",1208],[5,"ConfigBuilder",1208],[5,"SupportedProtocolVersion",1209],[5,"CryptoProvider",1210],[5,"Arc",1211],[5,"WantsVersions",1208],[5,"AcceptorService",423],[5,"Acceptor",423],[5,"TlsStream",423],[5,"TlsStream",1206],[5,"ServerConfig",468,1207],[5,"WantsVerifier",1208],[5,"ConfigBuilder",1208],[5,"CryptoProvider",1210],[10,"TimeProvider",1212],[5,"WantsVersions",1208],[5,"SupportedProtocolVersion",1209],[5,"ConnectInfo",502,1213],[17,"Item"],[6,"SocketAddr",1214],[10,"Iterator",1215],[10,"ExactSizeIterator",1216],[10,"FusedIterator",1217],[10,"Clone",1218],[10,"Host",502,1219],[5,"ConnectorService",502,1220],[5,"ResolverService",502,1221],[5,"Connector",502,1220],[5,"Resolver",502,1221],[10,"Resolve",502,1222],[5,"Connection",502,1223],[10,"PartialEq",1224],[6,"ConnectError",502,1225],[10,"Hash",1226],[10,"Hasher",1226],[1,"str"],[1,"tuple"],[1,"u16"],[5,"Vec",1227],[5,"Box",1228],[8,"LocalBoxFuture",1229],[10,"Into",1180],[10,"IntoIterator",1230],[6,"IpAddr",1231],[5,"TlsConnector",642],[5,"TlsConnector",661,1195],[1,"i32"],[10,"AsRawFd",1232],[5,"TlsConnectorBuilder",1195],[5,"TlsStream",1195],[6,"HandshakeError",1195],[5,"AllowStd",1187],[5,"Error",1190],[5,"TlsConnectorService",693],[5,"TlsConnector",693],[5,"SslConnector",725,1200],[5,"Error",725,1202],[6,"SSL_METHOD",1233],[5,"SslConnectorBuilder",725,1200],[5,"ErrorCode",1202],[5,"ConnectConfiguration",1200],[5,"TlsConnectorService",835],[5,"TlsConnector",835],[5,"RootCertStore",1234],[5,"ClientConfig",869,1235],[5,"AsyncTlsStream",869],[5,"ClientConnection",1235],[5,"TlsConnectorService",909],[5,"TlsConnector",909],[5,"RootCertStore",1234],[5,"ClientConfig",943,1235],[5,"AsyncTlsStream",943],[5,"ClientConnection",1235],[5,"TlsConnectorService",982],[5,"TlsConnector",982],[5,"RootCertStore",1236],[5,"ClientConfig",1016,1235],[5,"AsyncTlsStream",1016],[5,"DangerousClientConfig",1237],[5,"ClientConnection",1235],[5,"TlsConnectorService",1059],[5,"TlsConnector",1059],[5,"RootCertStore",1236],[5,"ClientConfig",1093,1235],[5,"AsyncTlsStream",1093],[5,"DangerousClientConfig",1237],[5,"ClientConnection",1238],[5,"TcpConnectorService",1145],[5,"TcpConnector",1145]],"r":[[70,1195],[71,1187],[144,1201],[145,1202],[147,1202],[150,1201],[151,1200],[152,1200],[259,1207],[327,1207],[396,1207],[468,1207],[502,1225],[503,1213],[504,1223],[505,1220],[506,1220],[507,1219],[511,1222],[512,1221],[514,1221],[662,1195],[726,1202],[728,1202],[730,1200],[731,1200],[732,1201],[870,1235],[871,1239],[944,1235],[945,1239],[1017,1235],[1018,1239],[1094,1235],[1095,1239]],"b":[[8,"impl-Debug-for-TlsError%3CTlsErr,+SvcErr%3E"],[9,"impl-Display-for-TlsError%3CTlsErr,+SvcErr%3E"],[80,"impl-Debug-for-Error"],[81,"impl-Display-for-Error"],[555,"impl-Debug-for-ConnectError"],[556,"impl-Display-for-ConnectError"],[557,"impl-Debug-for-ConnectInfo%3CR%3E"],[558,"impl-Display-for-ConnectInfo%3CR%3E"],[767,"impl-Debug-for-Error"],[768,"impl-Display-for-Error"],[769,"impl-Debug-for-HandshakeError%3CS%3E"],[770,"impl-Display-for-HandshakeError%3CS%3E"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAM8ChgAHAAMAFQAEAB0ADAAwAAIANAAGAD0ACQBKAAkAVQABAFoACABmAAwAeQACAH0ABgCGAAkAnQAKAKkABQCxAAcAvQAAAMkADQDaAAwA7QACAPEABgD6AAkABgEBAAoBAwAXAQMAHgEMADEBAgA1AQYAPgEJAEoBAQBOAQMAXAEDAGMBDAB2AQIAegEGAIMBCQCPAQEAlQECAJkBAACkAQMAqwEMAL4BAgDCAQYAywEJANcBAQDhAQIA5wEAAPMBAwAGAhsAJAILADQCAAA4AgAAQwIBAEYCAQBPAgEAUgIBAGQCAABnAhoAhAIFAIwCAQCPAgEAkgIDAJgCBACeAgIAogIBAKsCCgC4AgoAxwIBAMoCAQDOAgcA4QILAO8CBgD6AgEA/gIFAAcDAAAJAwAAFwMBAB4DAAAgAwAAIgMBACYDAQApAwAALQMVAEYDCgBVAwEAWQMBAF0DBwBoAwAAagMEAHEDAgB3AwEAewMBAH8DAACCAwIAhwMGAJADCgCfAwEAowMBAKcDBwCyAwAAtAMEALsDAgDAAwEAxAMBAMgDAADLAwIA0AMGANkDCgDoAwEA7AMBAPADBwD7AwAA/QMEAAYEAgANBAEAEQQBABUEAAAYBAIAHQQGACYECgA1BAEAOQQBAD0EBwBIBAAASgQEAFcEAgBgBAEAZAQBAGgEAQBsBAIAcwQGAHwEDgCPBAMAlAQHAA==","a":{"dtls_method":[764],"ssl_accept":[155],"ssl_connect":[174],"ssl_get_ex_new_index":[199],"ssl_new":[198],"tls_client_method":[810],"tls_method":[809],"tls_server_method":[811]}}],["actix_tracing",{"t":"FFNNNNNNNNNNNNNNNNNNHNNNNNN","n":["TracingService","TracingTransform","borrow","","borrow_mut","","call","clone","clone_into","clone_to_uninit","from","","into","","into_service","new","","new_transform","poll_ready","to_owned","trace","try_from","","try_into","","type_id",""],"q":[[0,"actix_tracing"],[27,"actix_service"],[28,"tracing::span"],[29,"core::option"],[30,"core::ops::function"],[31,"core::clone"],[32,"core::task::wake"],[33,"core::result"],[34,"core::task::poll"],[35,"actix_service::transform"],[36,"core::any"]],"i":"``Aff1000001010010100`101010","f":"``{b{{b{c}}}{}}0{{{b{d}}}{{b{dc}}}{}}0{{{b{{f{eg}}}}c}i{}{{h{c}}}{{A`{{b{c}}}{{j{{n{l}}}}}}}{}}{{{b{{f{ce}}}}}{{f{ce}}}AbAb}{{b{b{dc}}}Ad{}}{bAd}{cc{}}0{{}c{}}00{c{{Af{egc}}}{}{}{}}{{ce}{{f{ce}}}{}{}}{{{b{{Af{egi}}}}e}k{}{{h{c}}}{{An{c}{{Ah{}}{Aj{}}{Al{e}}}}}{{A`{{b{c}}}{{j{{n{l}}}}}}Ab}{}}{{{b{{f{eg}}}}{b{dB`}}}{{Bd{{Bb{Adi}}}}}{}{{h{c}}}{{A`{{b{c}}}{{j{{n{l}}}}}}}{}}{bc{}}{{gi}{{Bf{{Af{ei}}ec}}}{}{{An{c}}}{{Bh{ec}}}{{A`{{b{c}}}{{j{{n{l}}}}}}Ab}}{c{{Bb{e}}}{}{}}0{{}{{Bb{c}}}{}}0{bBj}0","D":"A`","p":[[1,"reference"],[0,"mut"],[5,"TracingService",0],[10,"Service",27],[17,"Output"],[5,"Span",28],[6,"Option",29],[10,"Fn",30],[10,"Clone",31],[1,"unit"],[5,"TracingTransform",0],[17,"Response"],[17,"Error"],[17,"Service"],[10,"ServiceFactory",27],[5,"Context",32],[6,"Result",33],[6,"Poll",34],[5,"ApplyTransform",35],[10,"IntoServiceFactory",27],[5,"TypeId",36]],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAABMAAwADAAcADwAFABYABQA="}],["actix_utils",{"t":"CCFFNNNNNNNNNNNNNNNNNNNNNNNNNGPFFPNNNNNNNNNNNNHNNNNNNNNNNNNNNNHNNNHHNNNNNNNNNNNNOO","n":["counter","future","Counter","CounterGuard","available","borrow","","borrow_mut","","clone","clone_into","clone_to_uninit","drop","fmt","","from","","get","into","","new","to_owned","total","try_from","","try_into","","type_id","","Either","Left","PollFn","Ready","Right","borrow","","","borrow_mut","","","clone","","clone_into","","clone_to_uninit","","err","fmt","","","from","","","into","","","into_future","","","into_inner","","left","ok","poll","","","poll_fn","ready","right","to_owned","","try_from","","","try_into","","","type_id","","","value",""],"q":[[0,"actix_utils"],[2,"actix_utils::counter"],[29,"actix_utils::future"],[80,"actix_utils::future::Either"],[82,"core::task::wake"],[83,"core::fmt"],[84,"core::result"],[85,"core::any"],[86,"actix_utils::future::either"],[87,"core::clone"],[88,"actix_utils::future::ready"],[89,"actix_utils::future::poll_fn"],[90,"core::pin"],[91,"core::task::poll"],[92,"core::ops::function"],[93,"core::future::future"]],"i":"````b0n1011101010110111101010`Aj``0B`1An120202020`120120120120202`120``220120120120BnC`","f":"````{{{d{b}}{d{f}}}h}{d{{d{c}}}{}}0{{{d{j}}}{{d{jc}}}{}}0{{{d{b}}}b}{{d{d{jc}}}l{}}{dl}{{{d{jn}}}l}{{{d{b}}{d{jA`}}}Ab}{{{d{n}}{d{jA`}}}Ab}{cc{}}0{{{d{b}}}n}{{}c{}}0{Adb}{dc{}}{{{d{b}}}Ad}{c{{Af{e}}}{}{}}0{{}{{Af{c}}}{}}0{dAh}0`````{d{{d{c}}}{}}00{{{d{j}}}{{d{jc}}}{}}00{{{d{{Aj{ce}}}}}{{Aj{ce}}}AlAl}{{{d{{An{c}}}}}{{An{c}}}Al}{{d{d{jc}}}l{}}0{dl}0{c{{An{{Af{ec}}}}}{}{}}{{{d{{B`{c}}}}{d{jA`}}}Ab{}}{{{d{{Aj{ce}}}}{d{jA`}}}AbBbBb}{{{d{{An{c}}}}{d{jA`}}}AbBb}{cc{}}00{{}c{}}00{{}}00{{{Aj{cc}}}c{}}{{{An{c}}}c{}}{c{{Aj{ce}}}{}{}}{c{{An{{Af{ce}}}}}{}{}}{{{Bd{{d{j{B`{e}}}}}}{d{jf}}}{{Bf{g}}}{}{{Bj{{d{jf}}}{{Bh{{Bf{c}}}}}}}{}}{{{Bd{{d{j{Aj{ce}}}}}}{d{jf}}}{{Bf{g}}}Bl{{Bl{}{{Bh{}}}}}{}}{{{Bd{{d{j{An{c}}}}}}{d{jf}}}{{Bf{c}}}{}}{e{{B`{e}}}{}{{Bj{{d{jf}}}{{Bh{{Bf{c}}}}}}}}{c{{An{c}}}{}}{c{{Aj{ec}}}{}{}}{dc{}}0{c{{Af{e}}}{}{}}00{{}{{Af{c}}}{}}00{dAh}00``","D":"D`","p":[[5,"Counter",2],[1,"reference"],[5,"Context",82],[1,"bool"],[0,"mut"],[1,"unit"],[5,"CounterGuard",2],[5,"Formatter",83],[8,"Result",83],[1,"usize"],[6,"Result",84],[5,"TypeId",85],[6,"Either",29,86],[10,"Clone",87],[5,"Ready",29,88],[5,"PollFn",29,89],[10,"Debug",83],[5,"Pin",90],[6,"Poll",91],[17,"Output"],[10,"FnMut",92],[10,"Future",93],[15,"Left",80],[15,"Right",80]],"r":[[29,86],[31,89],[32,88],[46,88],[62,88],[66,89],[67,88]],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAADIACAAGAAkAFgAAABgABQAjAAsAMAACADkAAgBAAAIARgAMAA=="}],["bytestring",{"t":"FNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["ByteString","as_bytes","as_ref","","","borrow","","borrow_mut","clone","clone_into","clone_to_uninit","cmp","default","deref","deserialize","eq","","fmt","","from","","","","from_bytes_unchecked","from_static","hash","into","into_bytes","new","partial_cmp","serialize","slice_ref","to_owned","to_string","try_from","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","try_into","type_id"],"q":[[0,"bytestring"],[107,"bytes::bytes"],[108,"core::cmp"],[109,"core::result"],[110,"serde::de"],[111,"core::convert"],[112,"core::fmt"],[113,"alloc::string"],[114,"alloc::boxed"],[115,"core::hash"],[116,"core::option"],[117,"serde::ser"],[118,"bytes::bytes_mut"],[119,"alloc::vec"],[120,"core::any"]],"i":"`b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","f":"`{{{d{b}}}{{d{f}}}}{{{d{b}}}{{d{h}}}}{{{d{b}}}{{d{{l{j}}}}}}{{{d{b}}}{{d{b}}}}2{d{{d{c}}}{}}{{{d{n}}}{{d{nc}}}{}}{{{d{b}}}b}{{d{d{nc}}}A`{}}{dA`}{{{d{b}}{d{b}}}Ab}{{}b}9{c{{Ad{b}}}Af}{{{d{b}}{d{c}}}Ah{{Aj{h}}}}{{{d{b}}{d{h}}}Ah}{{{d{b}}{d{nAl}}}An}0{{{d{h}}}b}{cc{}}{B`b}{{{Bb{h}}}b}{fb}4{{{d{b}}{d{nc}}}A`Bd}{{}c{}}{bf}<{{{d{b}}{d{b}}}{{Bf{Ab}}}}{{{d{b}}c}AdBh}{{{d{b}}{d{h}}}b}{dc{}}{dB`}{{{Bj{j}}}{{Ad{bc}}}{}}{{{d{{l{j}}}}}{{Ad{bc}}}{}}{Bl{{Ad{bc}}}{}}2{{{d{{Bj{j}}}}}{{Ad{bc}}}{}}303030303030303030303030303030303030{f{{Ad{bc}}}{}}1414141414141414141{c{{Ad{e}}}{}{}}2525252{{{Bn{j}}}{{Ad{bc}}}{}}6{{}{{Ad{c}}}{}}{dC`}","D":"Ad","p":[[5,"ByteString",0],[1,"reference"],[5,"Bytes",107],[1,"str"],[1,"u8"],[1,"slice"],[0,"mut"],[1,"unit"],[6,"Ordering",108],[6,"Result",109],[10,"Deserializer",110],[1,"bool"],[10,"AsRef",111],[5,"Formatter",112],[8,"Result",112],[5,"String",113],[5,"Box",114],[10,"Hasher",115],[6,"Option",116],[10,"Serializer",117],[1,"array"],[5,"BytesMut",118],[5,"Vec",119],[5,"TypeId",120]],"r":[],"b":[[2,"impl-AsRef%3Cstr%3E-for-ByteString"],[3,"impl-AsRef%3C%5Bu8%5D%3E-for-ByteString"],[4,"impl-AsRef%3CByteString%3E-for-ByteString"],[15,"impl-PartialEq%3CT%3E-for-ByteString"],[16,"impl-PartialEq%3Cstr%3E-for-ByteString"],[17,"impl-Debug-for-ByteString"],[18,"impl-Display-for-ByteString"],[19,"impl-From%3C%26str%3E-for-ByteString"],[21,"impl-From%3CString%3E-for-ByteString"],[22,"impl-From%3CBox%3Cstr%3E%3E-for-ByteString"],[34,"impl-TryFrom%3C%5Bu8;+29%5D%3E-for-ByteString"],[35,"impl-TryFrom%3C%26%5Bu8%5D%3E-for-ByteString"],[36,"impl-TryFrom%3CBytesMut%3E-for-ByteString"],[37,"impl-TryFrom%3C%5Bu8;+0%5D%3E-for-ByteString"],[38,"impl-TryFrom%3C%26%5Bu8;+0%5D%3E-for-ByteString"],[39,"impl-TryFrom%3C%5Bu8;+1%5D%3E-for-ByteString"],[40,"impl-TryFrom%3C%26%5Bu8;+1%5D%3E-for-ByteString"],[41,"impl-TryFrom%3C%5Bu8;+2%5D%3E-for-ByteString"],[42,"impl-TryFrom%3C%26%5Bu8;+2%5D%3E-for-ByteString"],[43,"impl-TryFrom%3C%5Bu8;+3%5D%3E-for-ByteString"],[44,"impl-TryFrom%3C%26%5Bu8;+3%5D%3E-for-ByteString"],[45,"impl-TryFrom%3C%5Bu8;+4%5D%3E-for-ByteString"],[46,"impl-TryFrom%3C%26%5Bu8;+4%5D%3E-for-ByteString"],[47,"impl-TryFrom%3C%5Bu8;+5%5D%3E-for-ByteString"],[48,"impl-TryFrom%3C%26%5Bu8;+5%5D%3E-for-ByteString"],[49,"impl-TryFrom%3C%5Bu8;+6%5D%3E-for-ByteString"],[50,"impl-TryFrom%3C%26%5Bu8;+6%5D%3E-for-ByteString"],[51,"impl-TryFrom%3C%5Bu8;+7%5D%3E-for-ByteString"],[52,"impl-TryFrom%3C%26%5Bu8;+7%5D%3E-for-ByteString"],[53,"impl-TryFrom%3C%5Bu8;+8%5D%3E-for-ByteString"],[54,"impl-TryFrom%3C%26%5Bu8;+8%5D%3E-for-ByteString"],[55,"impl-TryFrom%3C%5Bu8;+9%5D%3E-for-ByteString"],[56,"impl-TryFrom%3C%26%5Bu8;+9%5D%3E-for-ByteString"],[57,"impl-TryFrom%3C%5Bu8;+10%5D%3E-for-ByteString"],[58,"impl-TryFrom%3C%26%5Bu8;+10%5D%3E-for-ByteString"],[59,"impl-TryFrom%3C%5Bu8;+11%5D%3E-for-ByteString"],[60,"impl-TryFrom%3C%26%5Bu8;+11%5D%3E-for-ByteString"],[61,"impl-TryFrom%3C%5Bu8;+12%5D%3E-for-ByteString"],[62,"impl-TryFrom%3C%26%5Bu8;+12%5D%3E-for-ByteString"],[63,"impl-TryFrom%3C%5Bu8;+13%5D%3E-for-ByteString"],[64,"impl-TryFrom%3C%26%5Bu8;+13%5D%3E-for-ByteString"],[65,"impl-TryFrom%3C%5Bu8;+14%5D%3E-for-ByteString"],[66,"impl-TryFrom%3C%26%5Bu8;+14%5D%3E-for-ByteString"],[67,"impl-TryFrom%3C%5Bu8;+15%5D%3E-for-ByteString"],[68,"impl-TryFrom%3C%26%5Bu8;+15%5D%3E-for-ByteString"],[69,"impl-TryFrom%3C%5Bu8;+16%5D%3E-for-ByteString"],[70,"impl-TryFrom%3C%26%5Bu8;+16%5D%3E-for-ByteString"],[71,"impl-TryFrom%3C%5Bu8;+17%5D%3E-for-ByteString"],[72,"impl-TryFrom%3C%26%5Bu8;+17%5D%3E-for-ByteString"],[73,"impl-TryFrom%3C%5Bu8;+18%5D%3E-for-ByteString"],[74,"impl-TryFrom%3C%26%5Bu8;+18%5D%3E-for-ByteString"],[75,"impl-TryFrom%3CBytes%3E-for-ByteString"],[76,"impl-TryFrom%3C%26%5Bu8;+19%5D%3E-for-ByteString"],[77,"impl-TryFrom%3C%5Bu8;+20%5D%3E-for-ByteString"],[78,"impl-TryFrom%3C%26%5Bu8;+20%5D%3E-for-ByteString"],[79,"impl-TryFrom%3C%5Bu8;+21%5D%3E-for-ByteString"],[80,"impl-TryFrom%3C%26%5Bu8;+21%5D%3E-for-ByteString"],[81,"impl-TryFrom%3C%5Bu8;+22%5D%3E-for-ByteString"],[82,"impl-TryFrom%3C%26%5Bu8;+22%5D%3E-for-ByteString"],[83,"impl-TryFrom%3C%5Bu8;+23%5D%3E-for-ByteString"],[84,"impl-TryFrom%3C%26%5Bu8;+23%5D%3E-for-ByteString"],[85,"impl-TryFrom%3C%5Bu8;+24%5D%3E-for-ByteString"],[86,"impl-TryFrom%3C%26%5Bu8;+24%5D%3E-for-ByteString"],[87,"impl-TryFrom%3C%5Bu8;+25%5D%3E-for-ByteString"],[88,"impl-TryFrom%3C%26%5Bu8;+25%5D%3E-for-ByteString"],[89,"impl-TryFrom%3C%5Bu8;+26%5D%3E-for-ByteString"],[90,"impl-TryFrom%3C%26%5Bu8;+26%5D%3E-for-ByteString"],[91,"impl-TryFrom%3C%5Bu8;+27%5D%3E-for-ByteString"],[92,"impl-TryFrom%3C%26%5Bu8;+27%5D%3E-for-ByteString"],[93,"impl-TryFrom%3C%5Bu8;+28%5D%3E-for-ByteString"],[94,"impl-TryFrom%3C%26%5Bu8;+28%5D%3E-for-ByteString"],[96,"impl-TryFrom%3C%26%5Bu8;+29%5D%3E-for-ByteString"],[97,"impl-TryFrom%3C%5Bu8;+30%5D%3E-for-ByteString"],[98,"impl-TryFrom%3C%26%5Bu8;+30%5D%3E-for-ByteString"],[99,"impl-TryFrom%3C%5Bu8;+31%5D%3E-for-ByteString"],[100,"impl-TryFrom%3C%26%5Bu8;+31%5D%3E-for-ByteString"],[101,"impl-TryFrom%3C%5Bu8;+32%5D%3E-for-ByteString"],[102,"impl-TryFrom%3C%26%5Bu8;+32%5D%3E-for-ByteString"],[103,"impl-TryFrom%3CVec%3Cu8%3E%3E-for-ByteString"],[104,"impl-TryFrom%3C%5Bu8;+19%5D%3E-for-ByteString"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAGEABQADABEAFgABABoAAAAeAAEAIQBKAA=="}],["local_channel",{"t":"CFFFNNNNNNHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["mpsc","Receiver","SendError","Sender","borrow","","","borrow_mut","","","channel","clone","clone_into","clone_to_uninit","close","drop","","fmt","","","","from","","","into","","","into_inner","poll_close","poll_flush","poll_next","poll_ready","recv","send","sender","start_send","to_owned","to_string","try_from","","","try_into","","","try_poll_next","type_id","",""],"q":[[0,"local_channel"],[1,"local_channel::mpsc"],[48,"core::fmt"],[49,"core::pin"],[50,"core::task::wake"],[51,"core::result"],[52,"core::task::poll"],[53,"core::option"],[54,"alloc::string"],[55,"core::any"]],"i":"````nfh210`1111102210210210211010101122102100210","f":"````{b{{b{c}}}{}}00{{{b{d}}}{{b{dc}}}{}}00{{}{{j{{f{c}}{h{c}}}}}{}}{{{b{{f{c}}}}}{{f{c}}}{}}{{b{b{dc}}}l{}}{bl}{{{b{d{f{c}}}}}l{}}0{{{b{d{h{c}}}}}l{}}{{{b{{n{c}}}}{b{dA`}}}Ab{}}0{{{b{{f{c}}}}{b{dA`}}}AbAd}{{{b{{h{c}}}}{b{dA`}}}AbAd}{cc{}}00{{}c{}}00{{{n{c}}}c{}}{{{Af{{b{d{f{c}}}}}}{b{dAh}}}{{Al{{Aj{le}}}}}{}{}}{{{Af{{b{d{f{c}}}}}}{b{dAh}}}{{Al{{Aj{l{n{c}}}}}}}{}}{{{Af{{b{d{h{c}}}}}}{b{dAh}}}{{Al{{An{e}}}}}{}{}}2{{{b{d{h{c}}}}}{{An{c}}}{}}{{{b{{f{c}}}}c}{{Aj{l{n{c}}}}}{}}{{{b{{h{c}}}}}{{f{c}}}{}}{{{Af{{b{d{f{c}}}}}}c}{{Aj{l{n{c}}}}}{}}{bc{}}{bB`}{c{{Aj{e}}}{}{}}00{{}{{Aj{c}}}{}}00{{{Af{{b{dc}}}}{b{dAh}}}{{Al{{An{Aj}}}}}{}}{bBb}00","D":"Bb","p":[[1,"reference"],[0,"mut"],[5,"Sender",1],[5,"Receiver",1],[1,"tuple"],[1,"unit"],[5,"SendError",1],[5,"Formatter",48],[8,"Result",48],[10,"Debug",48],[5,"Pin",49],[5,"Context",50],[6,"Result",51],[6,"Poll",52],[6,"Option",53],[5,"String",54],[5,"TypeId",55]],"r":[],"b":[[17,"impl-Display-for-SendError%3CT%3E"],[18,"impl-Debug-for-SendError%3CT%3E"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAB8ABQAFAAUADAACABAABQAdAAMAJAAMAA=="}],["local_waker",{"t":"FNNNNNNNNNNNNN","n":["LocalWaker","borrow","borrow_mut","default","fmt","from","into","new","register","take","try_from","try_into","type_id","wake"],"q":[[0,"local_waker"],[14,"core::fmt"],[15,"core::task::wake"],[16,"core::option"],[17,"core::result"],[18,"core::any"]],"i":"`f000000000000","f":"`{b{{b{c}}}{}}{{{b{d}}}{{b{dc}}}{}}{{}f}{{{b{f}}{b{dh}}}j}{cc{}}{{}c{}}3{{{b{f}}{b{l}}}n}{{{b{f}}}{{A`{l}}}}{c{{Ab{e}}}{}{}}{{}{{Ab{c}}}{}}{bAd}{{{b{f}}}Af}","D":"A`","p":[[1,"reference"],[0,"mut"],[5,"LocalWaker",0],[5,"Formatter",14],[8,"Result",14],[5,"Waker",15],[1,"bool"],[6,"Option",16],[6,"Result",17],[5,"TypeId",18],[1,"unit"]],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAAYAAgACAAMACwACAA=="}]]')); +if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; +else if (window.initSearch) window.initSearch(searchIndex); +//{"start":39,"fragment_lengths":[5063,158,17781,2689,4346,35303,1534,2580,6420,1797,727]} \ No newline at end of file diff --git a/search.desc/actix_codec/actix_codec-desc-0-.js b/search.desc/actix_codec/actix_codec-desc-0-.js new file mode 100644 index 00000000..4a1a54b7 --- /dev/null +++ b/search.desc/actix_codec/actix_codec-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_codec", 0, "Codec utilities for working with framed protocols.\nReads bytes from a source.\nWrites bytes asynchronously.\nBytes codec. Reads/writes chunks of bytes from a stream.\nDecoding of frames via buffers.\nTrait of helper objects to write out messages as bytes, …\nThe type of unrecoverable frame decoding errors.\nThe type of encoding errors.\nA unified Stream and Sink interface to an underlying I/O …\nFramedParts contains an export of the data of a Framed …\nThe type of decoded frames.\nLines codec. Reads/writes line delimited strings.\nA wrapper around a byte buffer that is incrementally …\nAdvances the size of the filled region of the buffer.\nAsserts that the first n unfilled bytes of the buffer are …\nReturns the total capacity of the buffer.\nClears the buffer, resetting the filled region to empty.\nFlush write buffer and shutdown underlying I/O stream.\nThe codec object.\nReturns a mutable reference to the underlying codec.\nReturns a reference to the underlying codec.\nAttempts to decode a frame from the provided buffer of …\nA default method available to be called when there are no …\nEncodes a frame into the buffer provided.\nReturns a shared reference to the filled portion of the …\nReturns a mutable reference to the filled portion of the …\nFlush write buffer to underlying I/O stream.\nProvides a Stream and Sink interface for reading and …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nThis function returns a single object that is both Stream …\nReturns a mutable reference to the unfilled part of the …\nReturns a mutable reference to the first n bytes of the …\nReturns a shared reference to the initialized portion of …\nReturns a mutable reference to the initialized portion of …\nReturns a mutable reference to the entire buffer, without …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConsume the Frame, returning Frame with different codec.\nConsume the Frame, returning Frame with different io.\nConsumes the Frame, returning its underlying I/O stream, …\nThe inner transport used to read bytes to and write bytes …\nReturns a mutable reference to the underlying I/O stream.\nReturns a Pin of a mutable reference to the underlying I/O …\nReturns a reference to the underlying I/O stream wrapped …\nCheck if read buffer is empty.\nCheck if write buffer is empty.\nCheck if write buffer is full.\nCheck if framed is able to write more data.\nDetermines if this writer has an efficient …\nCreates a new ReadBuf from a fully initialized buffer.\nThis function returns a single object that is both Stream …\nCreates a new default FramedParts.\nTry to read underlying I/O stream and decode item.\nAttempts to flush the object, ensuring that any buffered …\nAttempts to read from the AsyncRead into buf.\nTry to read data from an AsyncRead into an implementer of …\nInitiates or attempts to shut down this writer, returning …\nAttempt to write bytes from buf into the object.\nLike poll_write, except that it writes from a slice of …\nAppends data to the buffer, advancing the written position …\nThe buffer with read but unprocessed data.\nReturns the number of bytes at the end of the slice that …\nConsume the Frame, returning Frame with different codec.\nSets the size of the filled region of the buffer.\nReturns a new ReadBuf comprised of the unfilled section up …\nReturns a mutable reference to the unfilled part of the …\nCreates a new ReadBuf from a fully uninitialized buffer.\nCreates a new FramedParts with read buffer.\nSerialize item and write to the inner buffer\nA buffer with unprocessed data which are not written yet.") \ No newline at end of file diff --git a/search.desc/actix_macros/actix_macros-desc-0-.js b/search.desc/actix_macros/actix_macros-desc-0-.js new file mode 100644 index 00000000..7369b384 --- /dev/null +++ b/search.desc/actix_macros/actix_macros-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_macros", 0, "Macros for Actix system and runtime.\nMarks async entry-point function to be executed by Actix …\nMarks async test function to be executed in an Actix …") \ No newline at end of file diff --git a/search.desc/actix_rt/actix_rt-desc-0-.js b/search.desc/actix_rt/actix_rt-desc-0-.js new file mode 100644 index 00000000..23c629e5 --- /dev/null +++ b/search.desc/actix_rt/actix_rt-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_rt", 0, "Tokio-based single-threaded async runtime for the Actix …\nAn Arbiter represents a thread that provides an …\nA handle for sending spawn and stop messages to an Arbiter.\nA Tokio-based runtime proxy.\nA manager for a per-thread distributed async runtime.\nRunner that keeps a System’s event loop alive until stop …\nGet handle to a the System’s initial Arbiter.\nRuns the provided future, blocking the current thread …\nRuns the provided future, blocking the current thread …\nReturn a handle to the current thread’s Arbiter’s …\nGet current running system.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturn a handle to the this Arbiter’s message sender.\nNumeric system identifier.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCheck if there is a System registered on the current …\nWait for Arbiter’s event loop to complete.\nMarks async entry-point function to be executed by Actix …\nTCP/UDP/Unix bindings (mostly Tokio re-exports).\nSpawn a new Arbiter thread and start its event loop with …\nReturns a new runtime initialized with default …\nCreate a new system.\nPins a value on the stack.\nStarts event loop and will return once System is stopped.\nRuns the event loop until stopped, returning the exit code.\nAsynchronous signal handling (Tokio re-exports).\nSpawns a future on the current thread as a new task.\nSend a future to the Arbiter’s thread and spawn it.\nSend a future to the Arbiter’s thread and spawn it.\nOffload a future onto the single-threaded runtime.\nSend a function to the Arbiter’s thread and execute it.\nSend a function to the Arbiter’s thread and execute it.\nInstruct Arbiter to stop processing it’s event loop.\nStop Arbiter from continuing it’s event loop.\nStop the system (with code 0).\nStop the system with a given exit code.\nTask management (Tokio re-exports).\nMarks async test function to be executed in an Actix …\nUtilities for tracking time (Tokio re-exports).\nRetrieves a reference to the underlying Tokio runtime …\nTry to get current running arbiter handle.\nTry to get current running system.\nReturns a Ready representing readiness for all operations.\nReturns the empty Ready set.\nReturns a Ready representing error readiness.\nReturns a Ready representing priority readiness.\nReturns a Ready representing readable readiness.\nReturns a Ready representing read closed readiness.\nDescribes the readiness state of an I/O resources.\nA TCP socket server, listening for connections.\nA TCP socket that has not yet been converted to a TcpStream…\nA TCP stream between a local and a remote socket.\nA UDP socket.\nAn I/O object representing a Unix datagram socket.\nA Unix socket which can accept connections from other Unix …\nA structure representing a connected Unix socket.\nReturns a Ready representing writable readiness.\nReturns a Ready representing write closed readiness.\nAccepts a new incoming connection from this listener.\nAccepts a new incoming connection to this listener.\nReads or writes from the socket using a user-provided IO …\nReads or writes from the socket using a user-provided IO …\nReads or writes from the socket using a user-provided IO …\nReads or writes from the socket using a user-provided IO …\nCreates a new TcpListener, which will be bound to the …\nBinds the socket to the given address.\nThis function will create a new UDP socket and attempt to …\nCreates a new UnixDatagram bound to the specified path.\nCreates a new UnixListener bound to the specified path.\nSets the value for the SO_BINDTODEVICE option on this …\nSets the value for the SO_BINDTODEVICE option on this …\nGets the value of the SO_BROADCAST option for this socket.\nEstablishes a TCP connection with a peer at the specified …\nOpens a TCP connection to a remote host.\nConnects the UDP socket setting the default destination …\nConnects the socket to the specified address.\nConnects to the socket named by path.\nGets the value for the SO_BINDTODEVICE option on this …\nGets the value for the SO_BINDTODEVICE option on this …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nConverts a RawFd to a TcpSocket.\nCreates new TcpListener from a std::net::TcpListener.\nCreates new TcpStream from a std::net::TcpStream.\nCreates new UdpSocket from a previously bound …\nCreates new UnixDatagram from a …\nCreates new UnixListener from a …\nCreates new UnixStream from a …\nConverts a std::net::TcpStream into a TcpSocket. The …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nSplits a TcpStream into a read half and a write half, …\nSplits a UnixStream into a read half and a write half, …\nTurns a tokio::net::TcpListener into a …\nTurns a tokio::net::TcpStream into a std::net::TcpStream.\nTurns a tokio::net::UdpSocket into a std::net::UdpSocket.\nTurns a tokio::net::UnixDatagram into a …\nTurns a tokio::net::UnixListener into a …\nTurns a tokio::net::UnixStream into a …\nReturns true if Ready is the empty set.\nReturns true if the value includes error readiness.\nReturns true if the value includes priority readiness.\nReturns true if the value includes read-closed readiness.\nReturns true if the value includes readable.\nReturns true if the value includes writable readiness.\nReturns true if the value includes write-closed readiness.\nExecutes an operation of the IP_ADD_MEMBERSHIP type.\nExecutes an operation of the IPV6_ADD_MEMBERSHIP type.\nGets the value of the SO_KEEPALIVE option on this socket.\nExecutes an operation of the IP_DROP_MEMBERSHIP type.\nExecutes an operation of the IPV6_DROP_MEMBERSHIP type.\nReads the linger duration for this socket by getting the …\nReads the linger duration for this socket by getting the …\nConverts the socket into a TcpListener.\nReturns the local address that this listener is bound to.\nGets the local address of this socket.\nReturns the local address that this stream is bound to.\nReturns the local address that this socket is bound to.\nReturns the local address that this socket is bound to.\nReturns the local socket address of this listener.\nReturns the socket address of the local half of this …\nGets the value of the IP_MULTICAST_LOOP option for this …\nGets the value of the IPV6_MULTICAST_LOOP option for this …\nGets the value of the IP_MULTICAST_TTL option for this …\nCreates a new socket configured for IPv4.\nCreates a new socket configured for IPv6.\nGets the value of the TCP_NODELAY option on this socket.\nGets the value of the TCP_NODELAY option on this socket.\nCreates an unnamed pair of connected sockets.\nCreates an unnamed pair of connected sockets.\nReceives data on the socket from the remote address to …\nReceives data from the socket, without removing it from …\nRetrieve the sender of the data at the head of the input …\nReturns the remote address that this stream is connected …\nReturns the socket address of the remote peer this socket …\nReturns the address of this socket’s peer.\nReturns the socket address of the remote half of this …\nReturns effective credentials of the process which called …\nPolls to accept a new incoming connection to this listener.\nPolls to accept a new incoming connection to this listener.\nAttempts to receive data on the socket, without removing …\nReceives data from the socket, without removing it from …\nRetrieve the sender of the data at the head of the input …\nPolls for read readiness.\nPolls for read readiness.\nAttempts to receive a single datagram message on the …\nAttempts to receive a single datagram message on the …\nAttempts to receive a single datagram on the socket.\nAttempts to receive a single datagram on the specified …\nPolls for read/receive readiness.\nPolls for read/receive readiness.\nAttempts to send data on the socket to the remote address …\nAttempts to send data on the socket to the remote address …\nPolls for write/send readiness.\nPolls for write/send readiness.\nAttempts to send data on the socket to a given address.\nAttempts to send data to the specified address.\nPolls for write readiness.\nPolls for write readiness.\nWaits for the socket to become readable.\nWaits for the socket to become readable.\nWaits for the socket to become readable.\nWaits for the socket to become readable.\nWaits for any of the requested ready states.\nWaits for any of the requested ready states.\nWaits for any of the requested ready states.\nWaits for any of the requested ready states.\nReceives a single datagram message on the socket from the …\nReceives data from the socket.\nReturns the size of the TCP receive buffer for this socket.\nReceives a single datagram message on the socket. On …\nReceives data from the socket.\nRetrieves the value set for SO_REUSEADDR on this socket.\nAllows the socket to bind to an in-use port. Only …\nSends data on the socket to the remote address that the …\nSends data on the socket to the socket’s peer.\nReturns the size of the TCP send buffer for this socket.\nSends data on the socket to the given address. On success, …\nSends data on the socket to the specified address.\nSets the value of the SO_BROADCAST option for this socket.\nSets value for the SO_KEEPALIVE option on this socket.\nSets the linger duration of this socket by setting the …\nSets the linger duration of this socket by setting the …\nSets the value of the IP_MULTICAST_LOOP option for this …\nSets the value of the IPV6_MULTICAST_LOOP option for this …\nSets the value of the IP_MULTICAST_TTL option for this …\nSets the value of the TCP_NODELAY option on this socket.\nSets the value of the TCP_NODELAY option on this socket.\nSets the size of the TCP receive buffer on this socket.\nAllows the socket to bind to an in-use address.\nAllows the socket to bind to an in-use port. Only …\nSets the size of the TCP send buffer on this socket.\nSets the value for the IP_TOS option on this socket.\nSets the value for the IP_TOS option on this socket.\nSets the value for the IP_TTL option on this socket.\nSets the value for the IP_TTL option on this socket.\nSets the value for the IP_TTL option on this socket.\nShuts down the read, write, or both halves of this …\nSplits a TcpStream into a read half and a write half, …\nSplits a UnixStream into a read half and a write half, …\nReturns the value of the SO_ERROR option.\nReturns the value of the SO_ERROR option.\nReturns the value of the SO_ERROR option.\nReturns the value of the SO_ERROR option.\nReturns the value of the SO_ERROR option.\nReturns the value of the SO_ERROR option.\nGets the value of the IP_TOS option for this socket.\nGets the value of the IP_TOS option for this socket.\nConsumes stream, returning the tokio I/O object.\nConsumes stream, returning the tokio I/O object.\nConsumes stream, returning the tokio I/O object.\nConsumes stream, returning the Tokio I/O object.\nConsumes stream, returning the tokio I/O object.\nConsumes stream, returning the tokio I/O object.\nTries to read or write from the socket using a …\nTries to read or write from the socket using a …\nTries to read or write from the socket using a …\nTries to read or write from the socket using a …\nTries to receive data on the socket without removing it …\nTry to retrieve the sender of the data at the head of the …\nTries to read data from the stream into the provided …\nTry to read data from the stream into the provided buffer, …\nTries to read data from the stream into the provided …\nTries to read data from the stream into the provided …\nTries to receive a single datagram message on the socket …\nTries to receive a datagram from the peer without waiting.\nTries to receive a single datagram message on the socket. …\nTries to receive data from the socket without waiting.\nTries to send data on the socket to the remote address to …\nTries to send a datagram to the peer without waiting.\nTries to send data on the socket to the given address, but …\nTries to send a datagram to the peer without waiting.\nTry to write a buffer to the stream, returning how many …\nTries to write a buffer to the stream, returning how many …\nTries to write several buffers to the stream, returning …\nTries to write several buffers to the stream, returning …\nGets the value of the IP_TTL option for this socket.\nGets the value of the IP_TTL option for this socket.\nGets the value of the IP_TTL option for this socket.\nCreates a new UnixDatagram which is not bound to any …\nWaits for the socket to become writable.\nWaits for the socket to become writable.\nWaits for the socket to become writable.\nWaits for the socket to become writable.\nCompletes when a “ctrl-c” notification is sent to the …\nUnix specific signals (Tokio re-exports).\nAn listener for receiving a particular type of OS signal.\nRepresents the specific kind of signal to listen for.\nRepresents the SIGALRM signal.\nGet the signal’s numeric value.\nRepresents the SIGCHLD signal.\nReturns the argument unchanged.\nReturns the argument unchanged.\nAllows for listening to any valid OS signal.\nRepresents the SIGHUP signal.\nRepresents the SIGINT signal.\nCalls U::from(self).\nCalls U::from(self).\nRepresents the SIGIO signal.\nRepresents the SIGPIPE signal.\nPolls to receive the next signal notification event, …\nRepresents the SIGQUIT signal.\nReceives the next signal notification event.\nCreates a new listener which will receive notifications …\nRepresents the SIGTERM signal.\nRepresents the SIGUSR1 signal.\nRepresents the SIGUSR2 signal.\nRepresents the SIGWINCH signal.\nTask failed to execute to completion.\nAn owned permission to join on a task (await its …\nAbort the task associated with the handle.\nReturns a new AbortHandle that can be used to remotely …\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nConsumes the join error, returning the object with which …\nReturns true if the error was caused by the task being …\nChecks if the task associated with this JoinHandle has …\nReturns true if the error was caused by the task panicking.\nRuns the provided closure on a thread where blocking is …\nConsumes the join error, returning the object with which …\nYields execution back to the Tokio runtime.\nA measurement of a monotonically nondecreasing clock. …\nInterval returned by interval and interval_at.\nFuture returned by sleep and sleep_until.\nFuture returned by timeout and timeout_at.\nReturns Some(t) where t is the time self + duration if t …\nReturns the amount of time elapsed from another instant to …\nReturns Some(t) where t is the time self - duration if t …\nReturns the instant at which the future will complete.\nReturns the amount of time elapsed from another instant to …\nReturns the amount of time elapsed since this instant was …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCreate a tokio::time::Instant from a std::time::Instant.\nGets a mutable reference to the underlying value in this …\nGets a reference to the underlying value in this timeout.\nCreates new Interval that yields with interval of period. …\nCreates new Interval that yields with interval of period …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConsumes this timeout, returning the underlying value.\nConvert the value into a std::time::Instant.\nReturns true if Sleep has elapsed.\nReturns the MissedTickBehavior strategy currently being …\nReturns an instant corresponding to “now”.\nReturns the period of the interval.\nPolls for the next instant in the interval to be reached.\nResets the interval to complete one period after the …\nResets the Sleep instance to a new deadline.\nResets the interval after the specified std::time::Duration…\nResets the interval to a crate::time::Instant deadline.\nResets the interval immediately.\nReturns the amount of time elapsed from another instant to …\nSets the MissedTickBehavior strategy that should be used.\nWaits until duration has elapsed.\nWaits until deadline is reached.\nCompletes when the next instant in the interval has been …\nRequires a Future to complete before the specified …") \ No newline at end of file diff --git a/search.desc/actix_server/actix_server-desc-0-.js b/search.desc/actix_server/actix_server-desc-0-.js new file mode 100644 index 00000000..6831a683 --- /dev/null +++ b/search.desc/actix_server/actix_server-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_server", 0, "General purpose TCP server.\nMPTCP will not be used when binding sockets.\nMultipath TCP (MPTCP) preference.\nMPTCP will be used when binding sockets (with no fallback).\nGeneral purpose TCP server that runs services receiving …\nServer builder.\nServer handle.\nMPTCP will be attempted when binding sockets. If errors …\nA testing server.\nSet the maximum number of pending connections.\nAdds new service to the server.\nAdds new service to the server using a UDS (unix domain …\nCreate server build.\nDisables OS signal handling.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nGet a Server handle that can be used issue commands and …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nAdds service to the server using a socket listener already …\nAdds new service to the server using a UDS (unix domain …\nSets the maximum per-worker number of concurrent …\nSets MultiPath TCP (MPTCP) preference on bound sockets.\nCreate new Server builder instance\nPause accepting incoming connections.\nResume accepting incoming connections.\nStarts processing incoming connections and return server …\nTimeout for graceful workers shutdown in seconds.\nStart new TestServer using application factory and default …\nStart new TestServer using application factory and server …\nStop incoming connection processing, stop all workers and …\nSets flag to stop Actix System after server shutdown.\nGet first available unused local address.\nSet max number of threads for each worker’s blocking …\nSets number of workers to start.") \ No newline at end of file diff --git a/search.desc/actix_service/actix_service-desc-0-.js b/search.desc/actix_service/actix_service-desc-0-.js new file mode 100644 index 00000000..52925fd1 --- /dev/null +++ b/search.desc/actix_service/actix_service-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_service", 0, "See Service docs for information on this crate’s …\nApply a Transform to a Service.\nService factory configuration.\nErrors produced by the service.\nErrors produced by the service when polling readiness or …\nErrors produced by the created services.\nThe future response value.\nThe future response value.\nThe future of the Service instance.g\nErrors produced while building a transform service.\nErrors potentially raised while building a service.\nTrait for types that can be converted to a Service\nTrait for types that can be converted to a ServiceFactory\nResponses produced by the service.\nResponses given by the service.\nResponses given by the created services.\nAn asynchronous operation from Request to a Response.\nThe kind of Service created by this factory.\nAn extension trait for Services that provides a variety of …\nFactory for creating Services.\nAn extension trait for ServiceFactorys that provides a …\nDefines the interface of a service factory that wraps …\nThe TransformService value created by this factory\nAn extension trait for Transforms that provides a variety …\nAn implementation of poll_ready that always signals …\nCall another service after call to this one has resolved …\nCall another service after call to this one has resolved …\nCall another service after call to this one has resolved …\nCall another service after call to this one has resolved …\nApply a Transform to a Service.\nConvert Fn(Config, &Service1) -> Future<Service2> fn to a …\nConvert …\nApply transform function to a service.\nService factory that produces apply_fn service.\nTrait object forms of services and service factories.\nProcess the request and return the response asynchronously.\nCreate ServiceFactory for function that can produce …\nCreate ServiceFactory for function that accepts config …\nCreate ServiceFactory for function that can act as a …\nAn implementation of poll_ready that forwards readiness …\nReturns the argument unchanged.\nCalls U::from(self).\nConvert Self to a ServiceFactory\nConvert object of type U to a service S\nConvert to a Service\nMap this service’s output to a different type, returning …\nMap this service’s output to a different type, returning …\nMap this service’s output to a different type, returning …\nMap this service’s output to a different type, returning …\nAdapt external config argument to a config for provided …\nMap this service’s error to a different error, returning …\nMap this service’s error to a different error, returning …\nMap this service’s error to a different error, returning …\nMap this service’s error to a different error, returning …\nMap this factory’s init error to a different error, …\nMap this factory’s init error to a different error, …\nReturn a new Transform whose init error is mapped to to a …\nReturn a new Transform whose init error is mapped to to a …\nCreate and return a new service asynchronously.\nCreates and returns a new Transform component, …\nReturns Ready when the service is able to process requests.\nReplace config with unit.\nA boxed future with no send bound or lifetime parameters.\nType alias for service trait object using Box.\nWrapper for a service factory that will map it’s …\nType alias for service trait object using Rc.\nWraps a service factory that returns service trait objects.\nReturns the argument unchanged.\nCalls U::from(self).\nWraps service as a trait object using RcService.\nWraps service as a trait object using BoxService.") \ No newline at end of file diff --git a/search.desc/actix_tls/actix_tls-desc-0-.js b/search.desc/actix_tls/actix_tls-desc-0-.js new file mode 100644 index 00000000..8d6df802 --- /dev/null +++ b/search.desc/actix_tls/actix_tls-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_tls", 0, "TLS acceptor and connector services for the Actix …\nTLS connection acceptor services.\nTCP and TLS connector services.\nWraps service errors.\nTLS handshake has timed-out.\nWraps TLS service errors.\nTLS handshake error, TLS timeout, or inner service error.\nReturns the argument unchanged.\nCalls U::from(self).\nCasts the infallible service error type returned from …\nSets the maximum per-worker concurrent TLS connection …\nnative-tls based TLS connection acceptor service.\nopenssl based TLS acceptor service.\nrustls v0.20 based TLS connection acceptor service.\nrustls v0.21 based TLS connection acceptor service.\nrustls v0.22 based TLS connection acceptor service.\nrustls v0.23 based TLS connection acceptor service.\nAccept TLS connections via the native-tls crate.\nNative-TLS based acceptor service.\nWraps a native-tls based async TLS stream in order to …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConstructs native-tls based acceptor service factory.\nRe-exports from native-tls that are useful for acceptors.\nLimit the amount of time that the acceptor will wait for a …\nAn error returned from the TLS implementation.\nA wrapper around a native_tls::TlsAcceptor, providing an …\nAccepts a new client connection with the provided stream.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nAccept TLS connections via the openssl crate.\nOpenSSL based acceptor service.\nWraps an openssl based async TLS stream in order to …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCreate openssl based acceptor service factory.\nRe-exports from openssl that are useful for acceptors.\nLimit the amount of time that the acceptor will wait for a …\nTerminate the handshake with a fatal alert.\nAn error returned from an ALPN selection callback.\nAn SSL error.\nThe handshake failed.\nAn error or intermediate state after a TLS handshake …\nDo not select a protocol, but continue the handshake.\nSetup failed.\nThe state of an SSL/TLS session.\nA type which wraps server-side streams in a TLS session.\nA builder for SslAcceptors.\nThe handshake encountered a WouldBlock error midway …\nInitiates a server-side TLS session on a stream.\nInitiates a server-side TLS handshake.\nConsumes the builder, returning a SslAcceptor.\nInitiates a client-side TLS handshake.\nReturns a shared reference to the inner raw SslContext.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConsumes the SslAcceptor, returning the inner raw …\nCreates a new builder configured to connect to non-legacy …\nCreates a new builder configured to connect to non-legacy …\nCreates a new builder configured to connect to modern …\nCreates a new builder configured to connect to modern …\nCreates a new Ssl.\nReturns a new extra data index.\nAccept TLS connections via the rustls crate.\nRustls based acceptor service.\nWraps a rustls based async TLS stream in order to …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConstructs rustls based acceptor service factory.\nRe-exports from rustls that are useful for acceptors.\nLimit the amount of time that the acceptor will wait for a …\nCommon configuration for a set of server sessions.\nProtocol names we support, most preferred first. If empty …\nCreate builder to build up the server configuration.\nHow to choose a server cert and key.\nReturns the argument unchanged.\nIgnore the client’s ciphersuite order. Instead, choose …\nCalls U::from(self).\nHow to output key material for debugging. The default …\nAmount of early data to accept for sessions created by …\nThe maximum size of TLS message we’ll emit. If None, we …\nWhether the server should send “0.5RTT” data. This …\nHow to store client sessions.\nHow to produce tickets.\nAccept TLS connections via the rustls crate.\nRustls based acceptor service.\nWraps a rustls based async TLS stream in order to …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConstructs rustls based acceptor service factory.\nRe-exports from rustls that are useful for acceptors.\nLimit the amount of time that the acceptor will wait for a …\nCommon configuration for a set of server sessions.\nProtocol names we support, most preferred first. If empty …\nCreate builder to build up the server configuration.\nHow to choose a server cert and key.\nReturns the argument unchanged.\nIgnore the client’s ciphersuite order. Instead, choose …\nCalls U::from(self).\nHow to output key material for debugging. The default …\nAmount of early data to accept for sessions created by …\nThe maximum size of TLS message we’ll emit. If None, we …\nWhether the server should send “0.5RTT” data. This …\nHow many TLS1.3 tickets to send immediately after a …\nHow to store client sessions.\nHow to produce tickets.\nAccept TLS connections via the rustls crate.\nRustls based acceptor service.\nWraps a rustls based async TLS stream in order to …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConstructs rustls based acceptor service factory.\nRe-exports from rustls that are useful for acceptors.\nLimit the amount of time that the acceptor will wait for a …\nCommon configuration for a set of server sessions.\nProtocol names we support, most preferred first. If empty …\nCreate a builder for a server configuration with the …\nCreate a builder for a server configuration with the …\nCreate a builder for a server configuration with a …\nHow to choose a server cert and key. This is usually set by\nAllows traffic secrets to be extracted after the handshake,\nReturns the argument unchanged.\nIgnore the client’s ciphersuite order. Instead, choose …\nCalls U::from(self).\nHow to output key material for debugging. The default …\nAmount of early data to accept for sessions created by …\nThe maximum size of plaintext input to be emitted in a …\nWhether the server should send “0.5RTT” data. This …\nHow many TLS1.3 tickets to send immediately after a …\nHow to store client sessions.\nHow to produce tickets.\nAccept TLS connections via the rustls crate.\nRustls based acceptor service.\nWraps a rustls based async TLS stream in order to …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConstructs rustls based acceptor service factory.\nRe-exports from rustls that are useful for acceptors.\nLimit the amount of time that the acceptor will wait for a …\nCommon configuration for a set of server sessions.\nProtocol names we support, most preferred first. If empty …\nCreate a builder for a server configuration with the …\nCreate a builder for a server configuration with no …\nCreate a builder for a server configuration with the …\nCreate a builder for a server configuration with a …\nCaching for compressed certificates.\nHow to compress the server’s certificate chain.\nHow to decompress the clients’s certificate chain.\nHow to choose a server cert and key. This is usually set by\nReturn the crypto provider used to construct this client …\nAllows traffic secrets to be extracted after the handshake,\nReturn true if connections made with this ServerConfig will\nReturns the argument unchanged.\nIgnore the client’s ciphersuite order. Instead, choose …\nCalls U::from(self).\nHow to output key material for debugging. The default …\nAmount of early data to accept for sessions created by …\nThe maximum size of plaintext input to be emitted in a …\nWhether the server should send “0.5RTT” data. This …\nHow many TLS1.3 tickets to send immediately after a …\nHow to store client sessions.\nHow to produce tickets.\nProvides the current system time\nErrors that can result from using a connector service.\nConnection request information.\nWraps underlying I/O and the connection request that …\nCombined resolver and TCP connector service factory.\nCombined resolver and TCP connector service.\nAn interface for types where host parts (hostname and …\nInvalid input.\nConnection IO error.\nNo DNS records.\nCustom async DNS resolvers.\nDNS resolver service factory.\nFailed to resolve the hostname.\nDNS resolver service.\nUnresolved host name.\nGet borrowed iterator of resolved request addresses.\nConstructs a new resolver factory with a custom resolver.\nConstructor for custom Resolve trait object and use it as …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nExtract hostname.\nReturns hostname.\nReturns request hostname.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nDeconstructs into IO and request parts.\nReturns a mutable reference to the underlying IO.\nReturns a shared reference to the underlying IO.\nGiven DNS lookup information, returns a future that …\nNative-TLS based connector service.\nConstruct new Connection from request and IO parts.\nConstructs new connector factory with the given resolver.\nConstructs new connection info using a request.\nOpenSSL based connector service.\nExtract optional port.\nExtract optional port.\nReturns request port.\nReplaces underlying IO, returning old IO and new Connection…\nReturns a reference to the connection request.\nReturns a reference to the connection request.\nRustls based connector service.\nRustls based connector service.\nRustls based connector service.\nRustls based connector service.\nBuild connector service.\nReturns a new resolver service.\nSet connection socket address.\nSet list of addresses.\nSet local address to connection with.\nSet connection port.\nTake owned iterator resolved request addresses.\nTCP connector service.\nConstructs new connection info from request and known …\nConnector service and factory using native-tls.\nReturns the argument unchanged.\nCalls U::from(self).\nConstructs new connector service from a native-tls …\nRe-exports from native-tls and tokio-native-tls that are …\nA wrapper around an underlying raw stream which implements …\nA builder for client-side TLS connections.\nReturns a new builder for a TlsConnector.\nInitiates a TLS handshake.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns a mutable reference to the inner stream.\nReturns a shared reference to the inner stream.\nCalls U::from(self).\nCalls U::from(self).\nReturns a new connector with default settings.\nConnector service factory using openssl.\nConnector service using openssl.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nConstructs new connector service factory from an openssl …\nRe-exports from openssl and tokio-openssl that are useful …\nConstructs new connector service from an openssl connector.\nAn asynchronous version of openssl::ssl::SslStream.\nAn SSL error.\nThe handshake failed.\nAn error or intermediate state after a TLS handshake …\nSetup failed.\nA type which wraps client-side streams in a TLS session.\nA builder for SslConnectors.\nA type specifying the kind of protocol an SslContext will …\nThe handshake encountered a WouldBlock error midway …\nA convenience method wrapping poll_accept.\nReturns a pointer to the underlying OpenSSL value.\nConsumes the builder, returning an SslConnector.\nCreates a new builder for TLS connections.\nReturns a structure allowing for configuration of a single …\nA convenience method wrapping poll_connect.\nInitiates a client-side TLS session on a stream.\nReturns a shared reference to the inner raw SslContext.\nA convenience method wrapping poll_do_handshake.\nSupport all versions of the DTLS protocol.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nConstructs an SslMethod from a pointer to the underlying …\nReturns a mutable reference to the underlying stream.\nReturns a pinned mutable reference to the underlying …\nReturns a shared reference to the underlying stream.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nConsumes the SslConnector, returning the inner raw …\nLike SslStream::new.\nA convenience method wrapping poll_peek.\nLike SslStream::accept.\nLike SslStream::connect.\nLike SslStream::do_handshake.\nLike SslStream::ssl_peek.\nLike SslStream::read_early_data.\nLike SslStream::write_early_data.\nA convenience method wrapping poll_read_early_data.\nReturns a shared reference to the Ssl object associated …\nSupport all versions of the TLS protocol.\nSupport all versions of the TLS protocol, explicitly as a …\nSupport all versions of the TLS protocol, explicitly as a …\nA convenience method wrapping poll_write_early_data.\nConnector service factory using rustls.\nConnector service using rustls.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nReturns root certificates via rustls-native-certs crate as …\nConstructs new connector service factory from a rustls …\nRe-exports from the rustls v0.20 ecosystem that are useful …\nConstructs new connector service from a rustls client …\nReturns standard root certificates from webpki-roots crate …\nA wrapper around an underlying raw stream which implements …\nCommon configuration for (typically) all connections made …\nWhich ALPN protocols we include in our client hello. If …\nCreate a builder to build up the client configuration.\nHow to decide what client auth certificate/keys to use.\nWhether to send data on the first flight (“early data”…\nWhether to send the Server Name Indication (SNI) extension …\nWhether to support RFC5077 tickets. You must provide a …\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nHow to output key material for debugging. The default …\nThe maximum size of TLS message we’ll emit. If None, we …\nNote: that it does not guarantee the final data to be sent.\nHow we store session data or tickets.\nConnector service factory using rustls.\nConnector service using rustls.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nReturns root certificates via rustls-native-certs crate as …\nConstructs new connector service factory from a rustls …\nRe-exports from the rustls v0.21 ecosystem that are useful …\nConstructs new connector service from a rustls client …\nReturns standard root certificates from webpki-roots crate …\nA wrapper around an underlying raw stream which implements …\nCommon configuration for (typically) all connections made …\nWhich ALPN protocols we include in our client hello. If …\nCreate a builder to build up the client configuration.\nHow to decide what client auth certificate/keys to use.\nWhether to send data on the first flight (“early data”…\nWhether to send the Server Name Indication (SNI) extension …\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nHow to output key material for debugging. The default …\nThe maximum size of TLS message we’ll emit. If None, we …\nNote: that it does not guarantee the final data to be sent.\nHow and when the client can resume a previous session.\nConnector service factory using rustls.\nConnector service using rustls.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nReturns root certificates via rustls-native-certs crate as …\nConstructs new connector service factory from a rustls …\nRe-exports from the rustls v0.22 ecosystem that are useful …\nConstructs new connector service from a rustls client …\nReturns standard root certificates from webpki-roots crate …\nA wrapper around an underlying raw stream which implements …\nCommon configuration for (typically) all connections made …\nWhich ALPN protocols we include in our client hello. If …\nCreate a builder for a client configuration with the …\nCreate a builder for a client configuration with the …\nCreate a builder for a client configuration with a …\nHow to decide what client auth certificate/keys to use.\nAccess configuration options whose use is dangerous and …\nWhether to send data on the first flight (“early data”…\nAllows traffic secrets to be extracted after the handshake,\nWhether to send the Server Name Indication (SNI) extension …\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nHow to output key material for debugging. The default …\nThe maximum size of plaintext input to be emitted in a …\nNote: that it does not guarantee the final data to be sent.\nHow and when the client can resume a previous session.\nConnector service factory using rustls.\nConnector service using rustls.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nReturns root certificates via rustls-native-certs crate as …\nConstructs new connector service factory from a rustls …\nRe-exports from the rustls v0.23 ecosystem that are useful …\nConstructs new connector service from a rustls client …\nReturns standard root certificates from webpki-roots crate …\nA wrapper around an underlying raw stream which implements …\nCommon configuration for (typically) all connections made …\nWhich ALPN protocols we include in our client hello. If …\nCreate a builder for a client configuration with the …\nCreate a builder for a client configuration with no …\nCreate a builder for a client configuration with the …\nCreate a builder for a client configuration with a …\nCaching for compressed certificates.\nHow to compress the client’s certificate chain.\nHow to decompress the server’s certificate chain.\nHow to decide what client auth certificate/keys to use.\nReturn the crypto provider used to construct this client …\nAccess configuration options whose use is dangerous and …\nWhether to send data on the first flight (“early data”…\nAllows traffic secrets to be extracted after the handshake,\nWhether to send the Server Name Indication (SNI) extension …\nReturn true if connections made with this ClientConfig will\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nHow to output key material for debugging. The default …\nThe maximum size of plaintext input to be emitted in a …\nNote: that it does not guarantee the final data to be sent.\nNote: that it does not guarantee the final data to be sent.\nHow and when the client can resume a previous session.\nProvides the current system time\nTCP connector service factory.\nTCP connector service.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nReturns a new TCP connector service.") \ No newline at end of file diff --git a/search.desc/actix_tracing/actix_tracing-desc-0-.js b/search.desc/actix_tracing/actix_tracing-desc-0-.js new file mode 100644 index 00000000..047ddb25 --- /dev/null +++ b/search.desc/actix_tracing/actix_tracing-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_tracing", 0, "Actix tracing - support for tokio tracing with Actix …\nA Service implementation that automatically enters/exits …\nA Transform implementation that wraps services with a …\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nWraps the provided service factory with a transform that …") \ No newline at end of file diff --git a/search.desc/actix_utils/actix_utils-desc-0-.js b/search.desc/actix_utils/actix_utils-desc-0-.js new file mode 100644 index 00000000..3ca2bb2f --- /dev/null +++ b/search.desc/actix_utils/actix_utils-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("actix_utils", 0, "Various utilities used in the Actix ecosystem.\nTask-notifying counter.\nHelpers for constructing futures.\nSimple counter with ability to notify task on reaching …\nAn RAII structure that keeps the underlying counter …\nReturns true if counter is below capacity. Otherwise, …\nReturns the argument unchanged.\nReturns the argument unchanged.\nCreate new counter guard, incrementing the counter.\nCalls U::from(self).\nCalls U::from(self).\nCreate Counter instance with max value.\nGet total number of acquired guards.\nCombines two different futures that have the same output …\nA value of type L.\nFuture for the poll_fn function.\nFuture for the ready function.\nA value of type R.\nCreates a future that is immediately ready with an error …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nUnwraps into inner value when left and right have a common …\nUnwraps the value from this immediately ready future.\nCreates new Either using left variant.\nCreates a future that is immediately ready with a success …\nCreates a future driven by the provided function that …\nCreates a future that is immediately ready with a value.\nCreates new Either using right variant.") \ No newline at end of file diff --git a/search.desc/bytestring/bytestring-desc-0-.js b/search.desc/bytestring/bytestring-desc-0-.js new file mode 100644 index 00000000..dae1c3af --- /dev/null +++ b/search.desc/bytestring/bytestring-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("bytestring", 0, "A UTF-8 encoded read-only string using Bytes as storage.\nAn immutable UTF-8 encoded string with Bytes as a storage.\nGet a reference to the underlying Bytes object.\nReturns the argument unchanged.\nCreates a new ByteString from a Bytes.\nCreates a new ByteString from a &'static str.\nCalls U::from(self).\nUnwraps this ByteString into the underlying Bytes object.\nCreates a new empty ByteString.\nReturns a new byte string that is equivalent to the given …") \ No newline at end of file diff --git a/search.desc/local_channel/local_channel-desc-0-.js b/search.desc/local_channel/local_channel-desc-0-.js new file mode 100644 index 00000000..dde61ec3 --- /dev/null +++ b/search.desc/local_channel/local_channel-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("local_channel", 0, "Non-thread-safe channels.\nA non-thread-safe multi-producer, single-consumer, …\nThe receiving end of a channel which implements the Stream …\nError returned when attempting to send after the channels…\nThe transmission end of a channel.\nCreates a unbounded in-memory channel with buffered …\nCloses the sender half.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nReturns the message that was attempted to be sent but …\nReceive the next value.\nSends the provided message along this channel.\nCreate an associated Sender.") \ No newline at end of file diff --git a/search.desc/local_waker/local_waker-desc-0-.js b/search.desc/local_waker/local_waker-desc-0-.js new file mode 100644 index 00000000..e2c3414a --- /dev/null +++ b/search.desc/local_waker/local_waker-desc-0-.js @@ -0,0 +1 @@ +searchState.loadedDescShard("local_waker", 0, "A synchronization primitive for thread-local task wakeup.\nA synchronization primitive for task wakeup.\nReturns the argument unchanged.\nCalls U::from(self).\nCreates a new, empty LocalWaker.\nRegisters the waker to be notified on calls to wake.\nReturns the last Waker passed to register, so that the …\nCalls wake on the last Waker passed to register.") \ No newline at end of file diff --git a/settings.html b/settings.html new file mode 100644 index 00000000..12fdb826 --- /dev/null +++ b/settings.html @@ -0,0 +1 @@ +Settings

Rustdoc settings

Back
\ No newline at end of file diff --git a/src-files.js b/src-files.js new file mode 100644 index 00000000..198adb61 --- /dev/null +++ b/src-files.js @@ -0,0 +1,3 @@ +var srcIndex = new Map(JSON.parse('[["actix_codec",["",[],["bcodec.rs","framed.rs","lib.rs","lines.rs"]]],["actix_macros",["",[],["lib.rs"]]],["actix_rt",["",[],["arbiter.rs","lib.rs","runtime.rs","system.rs"]]],["actix_server",["",[],["accept.rs","availability.rs","builder.rs","handle.rs","join_all.rs","lib.rs","server.rs","service.rs","signals.rs","socket.rs","test_server.rs","waker_queue.rs","worker.rs"]]],["actix_service",["",[],["and_then.rs","apply.rs","apply_cfg.rs","boxed.rs","ext.rs","fn_service.rs","lib.rs","macros.rs","map.rs","map_config.rs","map_err.rs","map_init_err.rs","pipeline.rs","ready.rs","then.rs","transform.rs","transform_err.rs"]]],["actix_tls",["",[["accept",[],["mod.rs","native_tls.rs","openssl.rs","rustls_0_20.rs","rustls_0_21.rs","rustls_0_22.rs","rustls_0_23.rs"]],["connect",[],["connect_addrs.rs","connection.rs","connector.rs","error.rs","host.rs","info.rs","mod.rs","native_tls.rs","openssl.rs","resolve.rs","resolver.rs","rustls_0_20.rs","rustls_0_21.rs","rustls_0_22.rs","rustls_0_23.rs","tcp.rs","uri.rs"]]],["lib.rs"]]],["actix_tracing",["",[],["lib.rs"]]],["actix_utils",["",[["future",[],["either.rs","mod.rs","poll_fn.rs","ready.rs"]]],["counter.rs","lib.rs"]]],["bytestring",["",[],["lib.rs"]]],["local_channel",["",[],["lib.rs","mpsc.rs"]]],["local_waker",["",[],["lib.rs"]]]]')); +createSrcSidebar(); +//{"start":36,"fragment_lengths":[69,36,70,201,250,403,37,108,34,47,35]} \ No newline at end of file diff --git a/src/actix_codec/bcodec.rs.html b/src/actix_codec/bcodec.rs.html new file mode 100644 index 00000000..ac08d196 --- /dev/null +++ b/src/actix_codec/bcodec.rs.html @@ -0,0 +1,65 @@ +bcodec.rs - source

actix_codec/
bcodec.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
use std::io;
+
+use bytes::{Buf, Bytes, BytesMut};
+
+use super::{Decoder, Encoder};
+
+/// Bytes codec. Reads/writes chunks of bytes from a stream.
+#[derive(Debug, Copy, Clone)]
+pub struct BytesCodec;
+
+impl Encoder<Bytes> for BytesCodec {
+    type Error = io::Error;
+
+    #[inline]
+    fn encode(&mut self, item: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> {
+        dst.extend_from_slice(item.chunk());
+        Ok(())
+    }
+}
+
+impl Decoder for BytesCodec {
+    type Item = BytesMut;
+    type Error = io::Error;
+
+    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
+        if src.is_empty() {
+            Ok(None)
+        } else {
+            Ok(Some(src.split()))
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_codec/framed.rs.html b/src/actix_codec/framed.rs.html new file mode 100644 index 00000000..f0f0c57e --- /dev/null +++ b/src/actix_codec/framed.rs.html @@ -0,0 +1,825 @@ +framed.rs - source

actix_codec/
framed.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
use std::{
+    fmt, io,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use bitflags::bitflags;
+use bytes::{Buf, BytesMut};
+use futures_core::{ready, Stream};
+use futures_sink::Sink;
+use pin_project_lite::pin_project;
+
+use crate::{AsyncRead, AsyncWrite, Decoder, Encoder};
+
+/// Low-water mark
+const LW: usize = 1024;
+/// High-water mark
+const HW: usize = 8 * 1024;
+
+bitflags! {
+    #[derive(Debug, Clone, Copy)]
+    struct Flags: u8 {
+        const EOF = 0b0001;
+        const READABLE = 0b0010;
+    }
+}
+
+pin_project! {
+    /// A unified `Stream` and `Sink` interface to an underlying I/O object, using the `Encoder` and
+    /// `Decoder` traits to encode and decode frames.
+    ///
+    /// Raw I/O objects work with byte sequences, but higher-level code usually wants to batch these
+    /// into meaningful chunks, called "frames". This method layers framing on top of an I/O object,
+    /// by using the `Encoder`/`Decoder` traits to handle encoding and decoding of message frames.
+    /// Note that the incoming and outgoing frame types may be distinct.
+    pub struct Framed<T, U> {
+        #[pin]
+        io: T,
+        codec: U,
+        flags: Flags,
+        read_buf: BytesMut,
+        write_buf: BytesMut,
+    }
+}
+
+impl<T, U> Framed<T, U>
+where
+    T: AsyncRead + AsyncWrite,
+    U: Decoder,
+{
+    /// This function returns a *single* object that is both `Stream` and `Sink`; grouping this into
+    /// a single object is often useful for layering things like gzip or TLS, which require both
+    /// read and write access to the underlying object.
+    pub fn new(io: T, codec: U) -> Framed<T, U> {
+        Framed {
+            io,
+            codec,
+            flags: Flags::empty(),
+            read_buf: BytesMut::with_capacity(HW),
+            write_buf: BytesMut::with_capacity(HW),
+        }
+    }
+}
+
+impl<T, U> Framed<T, U> {
+    /// Returns a reference to the underlying codec.
+    pub fn codec_ref(&self) -> &U {
+        &self.codec
+    }
+
+    /// Returns a mutable reference to the underlying codec.
+    pub fn codec_mut(&mut self) -> &mut U {
+        &mut self.codec
+    }
+
+    /// Returns a reference to the underlying I/O stream wrapped by `Frame`.
+    ///
+    /// Note that care should be taken to not tamper with the underlying stream of data coming in as
+    /// it may corrupt the stream of frames otherwise being worked with.
+    pub fn io_ref(&self) -> &T {
+        &self.io
+    }
+
+    /// Returns a mutable reference to the underlying I/O stream.
+    ///
+    /// Note that care should be taken to not tamper with the underlying stream of data coming in as
+    /// it may corrupt the stream of frames otherwise being worked with.
+    pub fn io_mut(&mut self) -> &mut T {
+        &mut self.io
+    }
+
+    /// Returns a `Pin` of a mutable reference to the underlying I/O stream.
+    pub fn io_pin(self: Pin<&mut Self>) -> Pin<&mut T> {
+        self.project().io
+    }
+
+    /// Check if read buffer is empty.
+    pub fn is_read_buf_empty(&self) -> bool {
+        self.read_buf.is_empty()
+    }
+
+    /// Check if write buffer is empty.
+    pub fn is_write_buf_empty(&self) -> bool {
+        self.write_buf.is_empty()
+    }
+
+    /// Check if write buffer is full.
+    pub fn is_write_buf_full(&self) -> bool {
+        self.write_buf.len() >= HW
+    }
+
+    /// Check if framed is able to write more data.
+    ///
+    /// `Framed` object considers ready if there is free space in write buffer.
+    pub fn is_write_ready(&self) -> bool {
+        self.write_buf.len() < HW
+    }
+
+    /// Consume the `Frame`, returning `Frame` with different codec.
+    pub fn replace_codec<U2>(self, codec: U2) -> Framed<T, U2> {
+        Framed {
+            codec,
+            io: self.io,
+            flags: self.flags,
+            read_buf: self.read_buf,
+            write_buf: self.write_buf,
+        }
+    }
+
+    /// Consume the `Frame`, returning `Frame` with different io.
+    pub fn into_map_io<F, T2>(self, f: F) -> Framed<T2, U>
+    where
+        F: Fn(T) -> T2,
+    {
+        Framed {
+            io: f(self.io),
+            codec: self.codec,
+            flags: self.flags,
+            read_buf: self.read_buf,
+            write_buf: self.write_buf,
+        }
+    }
+
+    /// Consume the `Frame`, returning `Frame` with different codec.
+    pub fn into_map_codec<F, U2>(self, f: F) -> Framed<T, U2>
+    where
+        F: Fn(U) -> U2,
+    {
+        Framed {
+            io: self.io,
+            codec: f(self.codec),
+            flags: self.flags,
+            read_buf: self.read_buf,
+            write_buf: self.write_buf,
+        }
+    }
+}
+
+impl<T, U> Framed<T, U> {
+    /// Serialize item and write to the inner buffer
+    pub fn write<I>(mut self: Pin<&mut Self>, item: I) -> Result<(), <U as Encoder<I>>::Error>
+    where
+        T: AsyncWrite,
+        U: Encoder<I>,
+    {
+        let this = self.as_mut().project();
+        let remaining = this.write_buf.capacity() - this.write_buf.len();
+        if remaining < LW {
+            this.write_buf.reserve(HW - remaining);
+        }
+
+        this.codec.encode(item, this.write_buf)?;
+        Ok(())
+    }
+
+    /// Try to read underlying I/O stream and decode item.
+    pub fn next_item(
+        mut self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+    ) -> Poll<Option<Result<<U as Decoder>::Item, U::Error>>>
+    where
+        T: AsyncRead,
+        U: Decoder,
+    {
+        loop {
+            let this = self.as_mut().project();
+            // Repeatedly call `decode` or `decode_eof` as long as it is "readable". Readable is
+            // defined as not having returned `None`. If the upstream has returned EOF, and the
+            // decoder is no longer readable, it can be assumed that the decoder will never become
+            // readable again, at which point the stream is terminated.
+
+            if this.flags.contains(Flags::READABLE) {
+                if this.flags.contains(Flags::EOF) {
+                    match this.codec.decode_eof(this.read_buf) {
+                        Ok(Some(frame)) => return Poll::Ready(Some(Ok(frame))),
+                        Ok(None) => return Poll::Ready(None),
+                        Err(err) => return Poll::Ready(Some(Err(err))),
+                    }
+                }
+
+                tracing::trace!("attempting to decode a frame");
+
+                match this.codec.decode(this.read_buf) {
+                    Ok(Some(frame)) => {
+                        tracing::trace!("frame decoded from buffer");
+                        return Poll::Ready(Some(Ok(frame)));
+                    }
+                    Err(err) => return Poll::Ready(Some(Err(err))),
+                    _ => (), // Need more data
+                }
+
+                this.flags.remove(Flags::READABLE);
+            }
+
+            debug_assert!(!this.flags.contains(Flags::EOF));
+
+            // Otherwise, try to read more data and try again. Make sure we've got room.
+            let remaining = this.read_buf.capacity() - this.read_buf.len();
+            if remaining < LW {
+                this.read_buf.reserve(HW - remaining)
+            }
+
+            let cnt = match tokio_util::io::poll_read_buf(this.io, cx, this.read_buf) {
+                Poll::Pending => return Poll::Pending,
+                Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err.into()))),
+                Poll::Ready(Ok(cnt)) => cnt,
+            };
+
+            if cnt == 0 {
+                this.flags.insert(Flags::EOF);
+            }
+            this.flags.insert(Flags::READABLE);
+        }
+    }
+
+    /// Flush write buffer to underlying I/O stream.
+    pub fn flush<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
+    where
+        T: AsyncWrite,
+        U: Encoder<I>,
+    {
+        let mut this = self.as_mut().project();
+        tracing::trace!("flushing framed transport");
+
+        while !this.write_buf.is_empty() {
+            tracing::trace!("writing; remaining={}", this.write_buf.len());
+
+            let n = ready!(this.io.as_mut().poll_write(cx, this.write_buf))?;
+
+            if n == 0 {
+                return Poll::Ready(Err(io::Error::new(
+                    io::ErrorKind::WriteZero,
+                    "failed to write frame to transport",
+                )
+                .into()));
+            }
+
+            // remove written data
+            this.write_buf.advance(n);
+        }
+
+        // Try flushing the underlying IO
+        ready!(this.io.poll_flush(cx))?;
+
+        tracing::trace!("framed transport flushed");
+        Poll::Ready(Ok(()))
+    }
+
+    /// Flush write buffer and shutdown underlying I/O stream.
+    pub fn close<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
+    where
+        T: AsyncWrite,
+        U: Encoder<I>,
+    {
+        let mut this = self.as_mut().project();
+        ready!(this.io.as_mut().poll_flush(cx))?;
+        ready!(this.io.as_mut().poll_shutdown(cx))?;
+        Poll::Ready(Ok(()))
+    }
+}
+
+impl<T, U> Stream for Framed<T, U>
+where
+    T: AsyncRead,
+    U: Decoder,
+{
+    type Item = Result<U::Item, U::Error>;
+
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+        self.next_item(cx)
+    }
+}
+
+impl<T, U, I> Sink<I> for Framed<T, U>
+where
+    T: AsyncWrite,
+    U: Encoder<I>,
+    U::Error: From<io::Error>,
+{
+    type Error = U::Error;
+
+    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        if self.is_write_ready() {
+            Poll::Ready(Ok(()))
+        } else {
+            self.flush(cx)
+        }
+    }
+
+    fn start_send(self: Pin<&mut Self>, item: I) -> Result<(), Self::Error> {
+        self.write(item)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        self.flush(cx)
+    }
+
+    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        self.close(cx)
+    }
+}
+
+impl<T, U> fmt::Debug for Framed<T, U>
+where
+    T: fmt::Debug,
+    U: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Framed")
+            .field("io", &self.io)
+            .field("codec", &self.codec)
+            .finish()
+    }
+}
+
+impl<T, U> Framed<T, U> {
+    /// This function returns a *single* object that is both `Stream` and `Sink`; grouping this into
+    /// a single object is often useful for layering things like gzip or TLS, which require both
+    /// read and write access to the underlying object.
+    ///
+    /// These objects take a stream, a read buffer and a write buffer. These fields can be obtained
+    /// from an existing `Framed` with the `into_parts` method.
+    pub fn from_parts(parts: FramedParts<T, U>) -> Framed<T, U> {
+        Framed {
+            io: parts.io,
+            codec: parts.codec,
+            flags: parts.flags,
+            write_buf: parts.write_buf,
+            read_buf: parts.read_buf,
+        }
+    }
+
+    /// Consumes the `Frame`, returning its underlying I/O stream, the buffer with unprocessed data,
+    /// and the codec.
+    ///
+    /// Note that care should be taken to not tamper with the underlying stream of data coming in as
+    /// it may corrupt the stream of frames otherwise being worked with.
+    pub fn into_parts(self) -> FramedParts<T, U> {
+        FramedParts {
+            io: self.io,
+            codec: self.codec,
+            flags: self.flags,
+            read_buf: self.read_buf,
+            write_buf: self.write_buf,
+        }
+    }
+}
+
+/// `FramedParts` contains an export of the data of a Framed transport.
+///
+/// It can be used to construct a new `Framed` with a different codec. It contains all current
+/// buffers and the inner transport.
+#[derive(Debug)]
+pub struct FramedParts<T, U> {
+    /// The inner transport used to read bytes to and write bytes to.
+    pub io: T,
+
+    /// The codec object.
+    pub codec: U,
+
+    /// The buffer with read but unprocessed data.
+    pub read_buf: BytesMut,
+
+    /// A buffer with unprocessed data which are not written yet.
+    pub write_buf: BytesMut,
+
+    flags: Flags,
+}
+
+impl<T, U> FramedParts<T, U> {
+    /// Creates a new default `FramedParts`.
+    pub fn new(io: T, codec: U) -> FramedParts<T, U> {
+        FramedParts {
+            io,
+            codec,
+            flags: Flags::empty(),
+            read_buf: BytesMut::new(),
+            write_buf: BytesMut::new(),
+        }
+    }
+
+    /// Creates a new `FramedParts` with read buffer.
+    pub fn with_read_buf(io: T, codec: U, read_buf: BytesMut) -> FramedParts<T, U> {
+        FramedParts {
+            io,
+            codec,
+            read_buf,
+            flags: Flags::empty(),
+            write_buf: BytesMut::new(),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_codec/lib.rs.html b/src/actix_codec/lib.rs.html new file mode 100644 index 00000000..c0157375 --- /dev/null +++ b/src/actix_codec/lib.rs.html @@ -0,0 +1,57 @@ +lib.rs - source

actix_codec/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
//! Codec utilities for working with framed protocols.
+//!
+//! Contains adapters to go from streams of bytes, [`AsyncRead`] and [`AsyncWrite`], to framed
+//! streams implementing [`Sink`] and [`Stream`]. Framed streams are also known as `transports`.
+//!
+//! [`Sink`]: futures_sink::Sink
+//! [`Stream`]: futures_core::Stream
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
+pub use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+pub use tokio_util::{
+    codec::{Decoder, Encoder},
+    io::poll_read_buf,
+};
+
+mod bcodec;
+mod framed;
+mod lines;
+
+pub use self::{
+    bcodec::BytesCodec,
+    framed::{Framed, FramedParts},
+    lines::LinesCodec,
+};
+
\ No newline at end of file diff --git a/src/actix_codec/lines.rs.html b/src/actix_codec/lines.rs.html new file mode 100644 index 00000000..f8bcb074 --- /dev/null +++ b/src/actix_codec/lines.rs.html @@ -0,0 +1,317 @@ +lines.rs - source

actix_codec/
lines.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
use std::io;
+
+use bytes::{Buf, BufMut, Bytes, BytesMut};
+use memchr::memchr;
+
+use super::{Decoder, Encoder};
+
+/// Lines codec. Reads/writes line delimited strings.
+///
+/// Will split input up by LF or CRLF delimiters. Carriage return characters at the end of lines are
+/// not preserved.
+#[derive(Debug, Copy, Clone, Default)]
+#[non_exhaustive]
+pub struct LinesCodec;
+
+impl<T: AsRef<str>> Encoder<T> for LinesCodec {
+    type Error = io::Error;
+
+    #[inline]
+    fn encode(&mut self, item: T, dst: &mut BytesMut) -> Result<(), Self::Error> {
+        let item = item.as_ref();
+        dst.reserve(item.len() + 1);
+        dst.put_slice(item.as_bytes());
+        dst.put_u8(b'\n');
+        Ok(())
+    }
+}
+
+impl Decoder for LinesCodec {
+    type Item = String;
+    type Error = io::Error;
+
+    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
+        if src.is_empty() {
+            return Ok(None);
+        }
+
+        let len = match memchr(b'\n', src) {
+            Some(n) => n,
+            None => {
+                return Ok(None);
+            }
+        };
+
+        // split up to new line char
+        let mut buf = src.split_to(len);
+        debug_assert_eq!(len, buf.len());
+
+        // remove new line char from source
+        src.advance(1);
+
+        match buf.last() {
+            // remove carriage returns at the end of buf
+            Some(b'\r') => buf.truncate(len - 1),
+
+            // line is empty
+            None => return Ok(Some(String::new())),
+
+            _ => {}
+        }
+
+        try_into_utf8(buf.freeze())
+    }
+
+    fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
+        match self.decode(src)? {
+            Some(frame) => Ok(Some(frame)),
+            None if src.is_empty() => Ok(None),
+            None => {
+                let buf = match src.last() {
+                    // if last line ends in a CR then take everything up to it
+                    Some(b'\r') => src.split_to(src.len() - 1),
+
+                    // take all bytes from source
+                    _ => src.split(),
+                };
+
+                if buf.is_empty() {
+                    return Ok(None);
+                }
+
+                try_into_utf8(buf.freeze())
+            }
+        }
+    }
+}
+
+// Attempts to convert bytes into a `String`.
+fn try_into_utf8(buf: Bytes) -> io::Result<Option<String>> {
+    String::from_utf8(buf.to_vec())
+        .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
+        .map(Some)
+}
+
+#[cfg(test)]
+mod tests {
+    use bytes::BufMut as _;
+
+    use super::*;
+
+    #[test]
+    fn lines_decoder() {
+        let mut codec = LinesCodec::default();
+        let mut buf = BytesMut::from("\nline 1\nline 2\r\nline 3\n\r\n\r");
+
+        assert_eq!("", codec.decode(&mut buf).unwrap().unwrap());
+        assert_eq!("line 1", codec.decode(&mut buf).unwrap().unwrap());
+        assert_eq!("line 2", codec.decode(&mut buf).unwrap().unwrap());
+        assert_eq!("line 3", codec.decode(&mut buf).unwrap().unwrap());
+        assert_eq!("", codec.decode(&mut buf).unwrap().unwrap());
+        assert!(codec.decode(&mut buf).unwrap().is_none());
+        assert!(codec.decode_eof(&mut buf).unwrap().is_none());
+
+        buf.put_slice(b"k");
+        assert!(codec.decode(&mut buf).unwrap().is_none());
+        assert_eq!("\rk", codec.decode_eof(&mut buf).unwrap().unwrap());
+
+        assert!(codec.decode(&mut buf).unwrap().is_none());
+        assert!(codec.decode_eof(&mut buf).unwrap().is_none());
+    }
+
+    #[test]
+    fn lines_encoder() {
+        let mut codec = LinesCodec::default();
+
+        let mut buf = BytesMut::new();
+
+        codec.encode("", &mut buf).unwrap();
+        assert_eq!(&buf[..], b"\n");
+
+        codec.encode("test", &mut buf).unwrap();
+        assert_eq!(&buf[..], b"\ntest\n");
+
+        codec.encode("a\nb", &mut buf).unwrap();
+        assert_eq!(&buf[..], b"\ntest\na\nb\n");
+    }
+
+    #[test]
+    fn lines_encoder_no_overflow() {
+        let mut codec = LinesCodec::default();
+
+        let mut buf = BytesMut::new();
+        codec.encode("1234567", &mut buf).unwrap();
+        assert_eq!(&buf[..], b"1234567\n");
+
+        let mut buf = BytesMut::new();
+        codec.encode("12345678", &mut buf).unwrap();
+        assert_eq!(&buf[..], b"12345678\n");
+
+        let mut buf = BytesMut::new();
+        codec.encode("123456789111213", &mut buf).unwrap();
+        assert_eq!(&buf[..], b"123456789111213\n");
+
+        let mut buf = BytesMut::new();
+        codec.encode("1234567891112131", &mut buf).unwrap();
+        assert_eq!(&buf[..], b"1234567891112131\n");
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_macros/lib.rs.html b/src/actix_macros/lib.rs.html new file mode 100644 index 00000000..c5e64c98 --- /dev/null +++ b/src/actix_macros/lib.rs.html @@ -0,0 +1,443 @@ +lib.rs - source

actix_macros/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
//! Macros for Actix system and runtime.
+//!
+//! The [`actix-rt`](https://docs.rs/actix-rt) crate must be available for macro output to compile.
+//!
+//! # Entry-point
+//! See docs for the [`#[main]`](macro@main) macro.
+//!
+//! # Tests
+//! See docs for the [`#[test]`](macro@test) macro.
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::parse::Parser as _;
+
+type AttributeArgs = syn::punctuated::Punctuated<syn::Meta, syn::Token![,]>;
+
+/// Marks async entry-point function to be executed by Actix system.
+///
+/// # Examples
+/// ```
+/// #[actix_rt::main]
+/// async fn main() {
+///     println!("Hello world");
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
+    let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {
+        Ok(input) => input,
+        // on parse err, make IDEs happy; see fn docs
+        Err(err) => return input_and_compile_error(item, err),
+    };
+
+    let parser = AttributeArgs::parse_terminated;
+    let args = match parser.parse(args.clone()) {
+        Ok(args) => args,
+        Err(err) => return input_and_compile_error(args, err),
+    };
+
+    let attrs = &input.attrs;
+    let vis = &input.vis;
+    let sig = &mut input.sig;
+    let body = &input.block;
+
+    if sig.asyncness.is_none() {
+        return syn::Error::new_spanned(
+            sig.fn_token,
+            "the async keyword is missing from the function declaration",
+        )
+        .to_compile_error()
+        .into();
+    }
+
+    let mut system = syn::parse_str::<syn::Path>("::actix_rt::System").unwrap();
+
+    for arg in &args {
+        match arg {
+            syn::Meta::NameValue(syn::MetaNameValue {
+                path,
+                value:
+                    syn::Expr::Lit(syn::ExprLit {
+                        lit: syn::Lit::Str(lit),
+                        ..
+                    }),
+                ..
+            }) => match path
+                .get_ident()
+                .map(|i| i.to_string().to_lowercase())
+                .as_deref()
+            {
+                Some("system") => match lit.parse() {
+                    Ok(path) => system = path,
+                    Err(_) => {
+                        return syn::Error::new_spanned(lit, "Expected path")
+                            .to_compile_error()
+                            .into();
+                    }
+                },
+                _ => {
+                    return syn::Error::new_spanned(arg, "Unknown attribute specified")
+                        .to_compile_error()
+                        .into();
+                }
+            },
+
+            _ => {
+                return syn::Error::new_spanned(arg, "Unknown attribute specified")
+                    .to_compile_error()
+                    .into();
+            }
+        }
+    }
+
+    sig.asyncness = None;
+
+    (quote! {
+        #(#attrs)*
+        #vis #sig {
+            <#system>::new().block_on(async move { #body })
+        }
+    })
+    .into()
+}
+
+/// Marks async test function to be executed in an Actix system.
+///
+/// # Examples
+/// ```
+/// #[actix_rt::test]
+/// async fn my_test() {
+///     assert!(true);
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
+    let mut input = match syn::parse::<syn::ItemFn>(item.clone()) {
+        Ok(input) => input,
+        // on parse err, make IDEs happy; see fn docs
+        Err(err) => return input_and_compile_error(item, err),
+    };
+
+    let parser = AttributeArgs::parse_terminated;
+    let args = match parser.parse(args.clone()) {
+        Ok(args) => args,
+        Err(err) => return input_and_compile_error(args, err),
+    };
+
+    let attrs = &input.attrs;
+    let vis = &input.vis;
+    let sig = &mut input.sig;
+    let body = &input.block;
+    let mut has_test_attr = false;
+
+    for attr in attrs {
+        if attr.path().is_ident("test") {
+            has_test_attr = true;
+        }
+    }
+
+    if sig.asyncness.is_none() {
+        return syn::Error::new_spanned(
+            input.sig.fn_token,
+            "the async keyword is missing from the function declaration",
+        )
+        .to_compile_error()
+        .into();
+    }
+
+    sig.asyncness = None;
+
+    let missing_test_attr = if has_test_attr {
+        quote! {}
+    } else {
+        quote! { #[::core::prelude::v1::test] }
+    };
+
+    let mut system = syn::parse_str::<syn::Path>("::actix_rt::System").unwrap();
+
+    for arg in &args {
+        match arg {
+            syn::Meta::NameValue(syn::MetaNameValue {
+                path,
+                value:
+                    syn::Expr::Lit(syn::ExprLit {
+                        lit: syn::Lit::Str(lit),
+                        ..
+                    }),
+                ..
+            }) => match path
+                .get_ident()
+                .map(|i| i.to_string().to_lowercase())
+                .as_deref()
+            {
+                Some("system") => match lit.parse() {
+                    Ok(path) => system = path,
+                    Err(_) => {
+                        return syn::Error::new_spanned(lit, "Expected path")
+                            .to_compile_error()
+                            .into();
+                    }
+                },
+                _ => {
+                    return syn::Error::new_spanned(arg, "Unknown attribute specified")
+                        .to_compile_error()
+                        .into();
+                }
+            },
+            _ => {
+                return syn::Error::new_spanned(arg, "Unknown attribute specified")
+                    .to_compile_error()
+                    .into();
+            }
+        }
+    }
+
+    (quote! {
+        #missing_test_attr
+        #(#attrs)*
+        #vis #sig {
+            <#system>::new().block_on(async { #body })
+        }
+    })
+    .into()
+}
+
+/// Converts the error to a token stream and appends it to the original input.
+///
+/// Returning the original input in addition to the error is good for IDEs which can gracefully
+/// recover and show more precise errors within the macro body.
+///
+/// See <https://github.com/rust-analyzer/rust-analyzer/issues/10468> for more info.
+fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream {
+    let compile_err = TokenStream::from(err.to_compile_error());
+    item.extend(compile_err);
+    item
+}
+
\ No newline at end of file diff --git a/src/actix_rt/arbiter.rs.html b/src/actix_rt/arbiter.rs.html new file mode 100644 index 00000000..f2ab8639 --- /dev/null +++ b/src/actix_rt/arbiter.rs.html @@ -0,0 +1,635 @@ +arbiter.rs - source

actix_rt/
arbiter.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
use std::{
+    cell::RefCell,
+    fmt,
+    future::Future,
+    pin::Pin,
+    sync::atomic::{AtomicUsize, Ordering},
+    task::{Context, Poll},
+    thread,
+};
+
+use futures_core::ready;
+use tokio::sync::mpsc;
+
+use crate::system::{System, SystemCommand};
+
+pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0);
+
+thread_local!(
+    static HANDLE: RefCell<Option<ArbiterHandle>> = const { RefCell::new(None) };
+);
+
+pub(crate) enum ArbiterCommand {
+    Stop,
+    Execute(Pin<Box<dyn Future<Output = ()> + Send>>),
+}
+
+impl fmt::Debug for ArbiterCommand {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ArbiterCommand::Stop => write!(f, "ArbiterCommand::Stop"),
+            ArbiterCommand::Execute(_) => write!(f, "ArbiterCommand::Execute"),
+        }
+    }
+}
+
+/// A handle for sending spawn and stop messages to an [Arbiter].
+#[derive(Debug, Clone)]
+pub struct ArbiterHandle {
+    tx: mpsc::UnboundedSender<ArbiterCommand>,
+}
+
+impl ArbiterHandle {
+    pub(crate) fn new(tx: mpsc::UnboundedSender<ArbiterCommand>) -> Self {
+        Self { tx }
+    }
+
+    /// Send a future to the [Arbiter]'s thread and spawn it.
+    ///
+    /// If you require a result, include a response channel in the future.
+    ///
+    /// Returns true if future was sent successfully and false if the [Arbiter] has died.
+    pub fn spawn<Fut>(&self, future: Fut) -> bool
+    where
+        Fut: Future<Output = ()> + Send + 'static,
+    {
+        self.tx
+            .send(ArbiterCommand::Execute(Box::pin(future)))
+            .is_ok()
+    }
+
+    /// Send a function to the [Arbiter]'s thread and execute it.
+    ///
+    /// Any result from the function is discarded. If you require a result, include a response
+    /// channel in the function.
+    ///
+    /// Returns true if function was sent successfully and false if the [Arbiter] has died.
+    pub fn spawn_fn<F>(&self, f: F) -> bool
+    where
+        F: FnOnce() + Send + 'static,
+    {
+        self.spawn(async { f() })
+    }
+
+    /// Instruct [Arbiter] to stop processing it's event loop.
+    ///
+    /// Returns true if stop message was sent successfully and false if the [Arbiter] has
+    /// been dropped.
+    pub fn stop(&self) -> bool {
+        self.tx.send(ArbiterCommand::Stop).is_ok()
+    }
+}
+
+/// An Arbiter represents a thread that provides an asynchronous execution environment for futures
+/// and functions.
+///
+/// When an arbiter is created, it spawns a new [OS thread](thread), and hosts an event loop.
+#[derive(Debug)]
+pub struct Arbiter {
+    tx: mpsc::UnboundedSender<ArbiterCommand>,
+    thread_handle: thread::JoinHandle<()>,
+}
+
+impl Arbiter {
+    /// Spawn a new Arbiter thread and start its event loop.
+    ///
+    /// # Panics
+    /// Panics if a [System] is not registered on the current thread.
+    #[cfg(not(all(target_os = "linux", feature = "io-uring")))]
+    #[allow(clippy::new_without_default)]
+    pub fn new() -> Arbiter {
+        Self::with_tokio_rt(|| {
+            crate::runtime::default_tokio_runtime().expect("Cannot create new Arbiter's Runtime.")
+        })
+    }
+
+    /// Spawn a new Arbiter using the [Tokio Runtime](tokio-runtime) returned from a closure.
+    ///
+    /// [tokio-runtime]: tokio::runtime::Runtime
+    #[cfg(not(all(target_os = "linux", feature = "io-uring")))]
+    pub fn with_tokio_rt<F>(runtime_factory: F) -> Arbiter
+    where
+        F: FnOnce() -> tokio::runtime::Runtime + Send + 'static,
+    {
+        let sys = System::current();
+        let system_id = sys.id();
+        let arb_id = COUNT.fetch_add(1, Ordering::Relaxed);
+
+        let name = format!("actix-rt|system:{}|arbiter:{}", system_id, arb_id);
+        let (tx, rx) = mpsc::unbounded_channel();
+
+        let (ready_tx, ready_rx) = std::sync::mpsc::channel::<()>();
+
+        let thread_handle = thread::Builder::new()
+            .name(name.clone())
+            .spawn({
+                let tx = tx.clone();
+                move || {
+                    let rt = crate::runtime::Runtime::from(runtime_factory());
+                    let hnd = ArbiterHandle::new(tx);
+
+                    System::set_current(sys);
+
+                    HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
+
+                    // register arbiter
+                    let _ = System::current()
+                        .tx()
+                        .send(SystemCommand::RegisterArbiter(arb_id, hnd));
+
+                    ready_tx.send(()).unwrap();
+
+                    // run arbiter event processing loop
+                    rt.block_on(ArbiterRunner { rx });
+
+                    // deregister arbiter
+                    let _ = System::current()
+                        .tx()
+                        .send(SystemCommand::DeregisterArbiter(arb_id));
+                }
+            })
+            .unwrap_or_else(|err| panic!("Cannot spawn Arbiter's thread: {name:?}: {err:?}"));
+
+        ready_rx.recv().unwrap();
+
+        Arbiter { tx, thread_handle }
+    }
+
+    /// Spawn a new Arbiter thread and start its event loop with `tokio-uring` runtime.
+    ///
+    /// # Panics
+    /// Panics if a [System] is not registered on the current thread.
+    #[cfg(all(target_os = "linux", feature = "io-uring"))]
+    #[allow(clippy::new_without_default)]
+    pub fn new() -> Arbiter {
+        let sys = System::current();
+        let system_id = sys.id();
+        let arb_id = COUNT.fetch_add(1, Ordering::Relaxed);
+
+        let name = format!("actix-rt|system:{}|arbiter:{}", system_id, arb_id);
+        let (tx, rx) = mpsc::unbounded_channel();
+
+        let (ready_tx, ready_rx) = std::sync::mpsc::channel::<()>();
+
+        let thread_handle = thread::Builder::new()
+            .name(name.clone())
+            .spawn({
+                let tx = tx.clone();
+                move || {
+                    let hnd = ArbiterHandle::new(tx);
+
+                    System::set_current(sys);
+
+                    HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
+
+                    // register arbiter
+                    let _ = System::current()
+                        .tx()
+                        .send(SystemCommand::RegisterArbiter(arb_id, hnd));
+
+                    ready_tx.send(()).unwrap();
+
+                    // run arbiter event processing loop
+                    tokio_uring::start(ArbiterRunner { rx });
+
+                    // deregister arbiter
+                    let _ = System::current()
+                        .tx()
+                        .send(SystemCommand::DeregisterArbiter(arb_id));
+                }
+            })
+            .unwrap_or_else(|err| panic!("Cannot spawn Arbiter's thread: {name:?}: {err:?}"));
+
+        ready_rx.recv().unwrap();
+
+        Arbiter { tx, thread_handle }
+    }
+
+    /// Sets up an Arbiter runner in a new System using the environment's local set.
+    pub(crate) fn in_new_system() -> ArbiterHandle {
+        let (tx, rx) = mpsc::unbounded_channel();
+
+        let hnd = ArbiterHandle::new(tx);
+
+        HANDLE.with(|cell| *cell.borrow_mut() = Some(hnd.clone()));
+
+        crate::spawn(ArbiterRunner { rx });
+
+        hnd
+    }
+
+    /// Return a handle to the this Arbiter's message sender.
+    pub fn handle(&self) -> ArbiterHandle {
+        ArbiterHandle::new(self.tx.clone())
+    }
+
+    /// Return a handle to the current thread's Arbiter's message sender.
+    ///
+    /// # Panics
+    /// Panics if no Arbiter is running on the current thread.
+    pub fn current() -> ArbiterHandle {
+        HANDLE.with(|cell| match *cell.borrow() {
+            Some(ref hnd) => hnd.clone(),
+            None => panic!("Arbiter is not running."),
+        })
+    }
+
+    /// Try to get current running arbiter handle.
+    ///
+    /// Returns `None` if no Arbiter has been started.
+    ///
+    /// Unlike [`current`](Self::current), this never panics.
+    pub fn try_current() -> Option<ArbiterHandle> {
+        HANDLE.with(|cell| cell.borrow().clone())
+    }
+
+    /// Stop Arbiter from continuing it's event loop.
+    ///
+    /// Returns true if stop message was sent successfully and false if the Arbiter has been dropped.
+    pub fn stop(&self) -> bool {
+        self.tx.send(ArbiterCommand::Stop).is_ok()
+    }
+
+    /// Send a future to the Arbiter's thread and spawn it.
+    ///
+    /// If you require a result, include a response channel in the future.
+    ///
+    /// Returns true if future was sent successfully and false if the Arbiter has died.
+    #[track_caller]
+    pub fn spawn<Fut>(&self, future: Fut) -> bool
+    where
+        Fut: Future<Output = ()> + Send + 'static,
+    {
+        self.tx
+            .send(ArbiterCommand::Execute(Box::pin(future)))
+            .is_ok()
+    }
+
+    /// Send a function to the Arbiter's thread and execute it.
+    ///
+    /// Any result from the function is discarded. If you require a result, include a response
+    /// channel in the function.
+    ///
+    /// Returns true if function was sent successfully and false if the Arbiter has died.
+    #[track_caller]
+    pub fn spawn_fn<F>(&self, f: F) -> bool
+    where
+        F: FnOnce() + Send + 'static,
+    {
+        self.spawn(async { f() })
+    }
+
+    /// Wait for Arbiter's event loop to complete.
+    ///
+    /// Joins the underlying OS thread handle. See [`JoinHandle::join`](thread::JoinHandle::join).
+    pub fn join(self) -> thread::Result<()> {
+        self.thread_handle.join()
+    }
+}
+
+/// A persistent future that processes [Arbiter] commands.
+struct ArbiterRunner {
+    rx: mpsc::UnboundedReceiver<ArbiterCommand>,
+}
+
+impl Future for ArbiterRunner {
+    type Output = ();
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        // process all items currently buffered in channel
+        loop {
+            match ready!(self.rx.poll_recv(cx)) {
+                // channel closed; no more messages can be received
+                None => return Poll::Ready(()),
+
+                // process arbiter command
+                Some(item) => match item {
+                    ArbiterCommand::Stop => {
+                        return Poll::Ready(());
+                    }
+                    ArbiterCommand::Execute(task_fut) => {
+                        tokio::task::spawn_local(task_fut);
+                    }
+                },
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_rt/lib.rs.html b/src/actix_rt/lib.rs.html new file mode 100644 index 00000000..e74e8f64 --- /dev/null +++ b/src/actix_rt/lib.rs.html @@ -0,0 +1,419 @@ +lib.rs - source

actix_rt/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
//! Tokio-based single-threaded async runtime for the Actix ecosystem.
+//!
+//! In most parts of the the Actix ecosystem, it has been chosen to use !Send futures. For this
+//! reason, a single-threaded runtime is appropriate since it is guaranteed that futures will not
+//! be moved between threads. This can result in small performance improvements over cases where
+//! atomics would otherwise be needed.
+//!
+//! To achieve similar performance to multi-threaded, work-stealing runtimes, applications
+//! using `actix-rt` will create multiple, mostly disconnected, single-threaded runtimes.
+//! This approach has good performance characteristics for workloads where the majority of tasks
+//! have similar runtime expense.
+//!
+//! The disadvantage is that idle threads will not steal work from very busy, stuck or otherwise
+//! backlogged threads. Tasks that are disproportionately expensive should be offloaded to the
+//! blocking task thread-pool using [`task::spawn_blocking`].
+//!
+//! # Examples
+//! ```no_run
+//! use std::sync::mpsc;
+//! use actix_rt::{Arbiter, System};
+//!
+//! let _ = System::new();
+//!
+//! let (tx, rx) = mpsc::channel::<u32>();
+//!
+//! let arbiter = Arbiter::new();
+//! arbiter.spawn_fn(move || tx.send(42).unwrap());
+//!
+//! let num = rx.recv().unwrap();
+//! assert_eq!(num, 42);
+//!
+//! arbiter.stop();
+//! arbiter.join().unwrap();
+//! ```
+//!
+//! # `io-uring` Support
+//!
+//! There is experimental support for using io-uring with this crate by enabling the
+//! `io-uring` feature. For now, it is semver exempt.
+//!
+//! Note that there are currently some unimplemented parts of using `actix-rt` with `io-uring`.
+//! In particular, when running a `System`, only `System::block_on` is supported.
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+#![allow(clippy::type_complexity)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
+#[cfg(all(not(target_os = "linux"), feature = "io-uring"))]
+compile_error!("io_uring is a linux only feature.");
+
+use std::future::Future;
+
+// Cannot define a main macro when compiled into test harness.
+// Workaround for https://github.com/rust-lang/rust/issues/62127.
+#[cfg(all(feature = "macros", not(test)))]
+pub use actix_macros::main;
+#[cfg(feature = "macros")]
+pub use actix_macros::test;
+
+mod arbiter;
+mod runtime;
+mod system;
+
+pub use tokio::pin;
+use tokio::task::JoinHandle;
+
+pub use self::{
+    arbiter::{Arbiter, ArbiterHandle},
+    runtime::Runtime,
+    system::{System, SystemRunner},
+};
+
+pub mod signal {
+    //! Asynchronous signal handling (Tokio re-exports).
+
+    #[cfg(unix)]
+    pub mod unix {
+        //! Unix specific signals (Tokio re-exports).
+        pub use tokio::signal::unix::*;
+    }
+    pub use tokio::signal::ctrl_c;
+}
+
+pub mod net {
+    //! TCP/UDP/Unix bindings (mostly Tokio re-exports).
+
+    use std::{
+        future::Future,
+        io,
+        task::{Context, Poll},
+    };
+
+    use tokio::io::{AsyncRead, AsyncWrite, Interest};
+    #[cfg(unix)]
+    pub use tokio::net::{UnixDatagram, UnixListener, UnixStream};
+    pub use tokio::{
+        io::Ready,
+        net::{TcpListener, TcpSocket, TcpStream, UdpSocket},
+    };
+
+    /// Extension trait over async read+write types that can also signal readiness.
+    #[doc(hidden)]
+    pub trait ActixStream: AsyncRead + AsyncWrite + Unpin {
+        /// Poll stream and check read readiness of Self.
+        ///
+        /// See [tokio::net::TcpStream::poll_read_ready] for detail on intended use.
+        fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>>;
+
+        /// Poll stream and check write readiness of Self.
+        ///
+        /// See [tokio::net::TcpStream::poll_write_ready] for detail on intended use.
+        fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>>;
+    }
+
+    impl ActixStream for TcpStream {
+        fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+            let ready = self.ready(Interest::READABLE);
+            tokio::pin!(ready);
+            ready.poll(cx)
+        }
+
+        fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+            let ready = self.ready(Interest::WRITABLE);
+            tokio::pin!(ready);
+            ready.poll(cx)
+        }
+    }
+
+    #[cfg(unix)]
+    impl ActixStream for UnixStream {
+        fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+            let ready = self.ready(Interest::READABLE);
+            tokio::pin!(ready);
+            ready.poll(cx)
+        }
+
+        fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+            let ready = self.ready(Interest::WRITABLE);
+            tokio::pin!(ready);
+            ready.poll(cx)
+        }
+    }
+
+    impl<Io: ActixStream + ?Sized> ActixStream for Box<Io> {
+        fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+            (**self).poll_read_ready(cx)
+        }
+
+        fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+            (**self).poll_write_ready(cx)
+        }
+    }
+}
+
+pub mod time {
+    //! Utilities for tracking time (Tokio re-exports).
+
+    pub use tokio::time::{
+        interval, interval_at, sleep, sleep_until, timeout, Instant, Interval, Sleep, Timeout,
+    };
+}
+
+pub mod task {
+    //! Task management (Tokio re-exports).
+
+    pub use tokio::task::{spawn_blocking, yield_now, JoinError, JoinHandle};
+}
+
+/// Spawns a future on the current thread as a new task.
+///
+/// If not immediately awaited, the task can be cancelled using [`JoinHandle::abort`].
+///
+/// The provided future is spawned as a new task; therefore, panics are caught.
+///
+/// # Panics
+/// Panics if Actix system is not running.
+///
+/// # Examples
+/// ```
+/// # use std::time::Duration;
+/// # actix_rt::Runtime::new().unwrap().block_on(async {
+/// // task resolves successfully
+/// assert_eq!(actix_rt::spawn(async { 1 }).await.unwrap(), 1);
+///
+/// // task panics
+/// assert!(actix_rt::spawn(async {
+///     panic!("panic is caught at task boundary");
+/// })
+/// .await
+/// .unwrap_err()
+/// .is_panic());
+///
+/// // task is cancelled before completion
+/// let handle = actix_rt::spawn(actix_rt::time::sleep(Duration::from_secs(100)));
+/// handle.abort();
+/// assert!(handle.await.unwrap_err().is_cancelled());
+/// # });
+/// ```
+#[track_caller]
+#[inline]
+pub fn spawn<Fut>(f: Fut) -> JoinHandle<Fut::Output>
+where
+    Fut: Future + 'static,
+    Fut::Output: 'static,
+{
+    tokio::task::spawn_local(f)
+}
+
\ No newline at end of file diff --git a/src/actix_rt/runtime.rs.html b/src/actix_rt/runtime.rs.html new file mode 100644 index 00000000..8447bfa7 --- /dev/null +++ b/src/actix_rt/runtime.rs.html @@ -0,0 +1,299 @@ +runtime.rs - source

actix_rt/
runtime.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
use std::{future::Future, io};
+
+use tokio::task::{JoinHandle, LocalSet};
+
+/// A Tokio-based runtime proxy.
+///
+/// All spawned futures will be executed on the current thread. Therefore, there is no `Send` bound
+/// on submitted futures.
+#[derive(Debug)]
+pub struct Runtime {
+    local: LocalSet,
+    rt: tokio::runtime::Runtime,
+}
+
+pub(crate) fn default_tokio_runtime() -> io::Result<tokio::runtime::Runtime> {
+    tokio::runtime::Builder::new_current_thread()
+        .enable_io()
+        .enable_time()
+        .build()
+}
+
+impl Runtime {
+    /// Returns a new runtime initialized with default configuration values.
+    #[allow(clippy::new_ret_no_self)]
+    pub fn new() -> io::Result<Self> {
+        let rt = default_tokio_runtime()?;
+
+        Ok(Runtime {
+            rt,
+            local: LocalSet::new(),
+        })
+    }
+
+    /// Offload a future onto the single-threaded runtime.
+    ///
+    /// The returned join handle can be used to await the future's result.
+    ///
+    /// See [crate root][crate] documentation for more details.
+    ///
+    /// # Examples
+    /// ```
+    /// let rt = actix_rt::Runtime::new().unwrap();
+    ///
+    /// // Spawn a future onto the runtime
+    /// let handle = rt.spawn(async {
+    ///     println!("running on the runtime");
+    ///     42
+    /// });
+    ///
+    /// assert_eq!(rt.block_on(handle).unwrap(), 42);
+    /// ```
+    ///
+    /// # Panics
+    /// This function panics if the spawn fails. Failure occurs if the executor is currently at
+    /// capacity and is unable to spawn a new future.
+    #[track_caller]
+    pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
+    where
+        F: Future + 'static,
+    {
+        self.local.spawn_local(future)
+    }
+
+    /// Retrieves a reference to the underlying Tokio runtime associated with this instance.
+    ///
+    /// The Tokio runtime is responsible for executing asynchronous tasks and managing
+    /// the event loop for an asynchronous Rust program. This method allows accessing
+    /// the runtime to interact with its features directly.
+    ///
+    /// In a typical use case, you might need to share the same runtime between different
+    /// modules of your project. For example, a module might require a `tokio::runtime::Handle`
+    /// to spawn tasks on the same runtime, or the runtime itself to configure more complex
+    /// behaviours.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use actix_rt::Runtime;
+    ///
+    /// mod module_a {
+    ///     pub fn do_something(handle: tokio::runtime::Handle) {
+    ///         handle.spawn(async {
+    ///             // Some asynchronous task here
+    ///         });
+    ///     }
+    /// }
+    ///
+    /// mod module_b {
+    ///     pub fn do_something_else(rt: &tokio::runtime::Runtime) {
+    ///         rt.spawn(async {
+    ///             // Another asynchronous task here
+    ///         });
+    ///     }
+    /// }
+    ///
+    /// let actix_runtime = actix_rt::Runtime::new().unwrap();
+    /// let tokio_runtime = actix_runtime.tokio_runtime();
+    ///
+    /// let handle = tokio_runtime.handle().clone();
+    ///
+    /// module_a::do_something(handle);
+    /// module_b::do_something_else(tokio_runtime);
+    /// ```
+    ///
+    /// # Returns
+    ///
+    /// An immutable reference to the `tokio::runtime::Runtime` instance associated with this
+    /// `Runtime` instance.
+    ///
+    /// # Note
+    ///
+    /// While this method provides an immutable reference to the Tokio runtime, which is safe to share across threads,
+    /// be aware that spawning blocking tasks on the Tokio runtime could potentially impact the execution
+    /// of the Actix runtime. This is because Tokio is responsible for driving the Actix system,
+    /// and blocking tasks could delay or deadlock other tasks in run loop.
+    pub fn tokio_runtime(&self) -> &tokio::runtime::Runtime {
+        &self.rt
+    }
+
+    /// Runs the provided future, blocking the current thread until the future completes.
+    ///
+    /// This function can be used to synchronously block the current thread until the provided
+    /// `future` has resolved either successfully or with an error. The result of the future is
+    /// then returned from this function call.
+    ///
+    /// Note that this function will also execute any spawned futures on the current thread, but
+    /// will not block until these other spawned futures have completed. Once the function returns,
+    /// any uncompleted futures remain pending in the `Runtime` instance. These futures will not run
+    /// until `block_on` or `run` is called again.
+    ///
+    /// The caller is responsible for ensuring that other spawned futures complete execution by
+    /// calling `block_on` or `run`.
+    #[track_caller]
+    pub fn block_on<F>(&self, f: F) -> F::Output
+    where
+        F: Future,
+    {
+        self.local.block_on(&self.rt, f)
+    }
+}
+
+impl From<tokio::runtime::Runtime> for Runtime {
+    fn from(rt: tokio::runtime::Runtime) -> Self {
+        Self {
+            local: LocalSet::new(),
+            rt,
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_rt/system.rs.html b/src/actix_rt/system.rs.html new file mode 100644 index 00000000..d7a0d69c --- /dev/null +++ b/src/actix_rt/system.rs.html @@ -0,0 +1,715 @@ +system.rs - source

actix_rt/
system.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
use std::{
+    cell::RefCell,
+    collections::HashMap,
+    future::Future,
+    io,
+    pin::Pin,
+    sync::atomic::{AtomicUsize, Ordering},
+    task::{Context, Poll},
+};
+
+use futures_core::ready;
+use tokio::sync::{mpsc, oneshot};
+
+use crate::{arbiter::ArbiterHandle, Arbiter};
+
+static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
+
+thread_local!(
+    static CURRENT: RefCell<Option<System>> = const { RefCell::new(None) };
+);
+
+/// A manager for a per-thread distributed async runtime.
+#[derive(Clone, Debug)]
+pub struct System {
+    id: usize,
+    sys_tx: mpsc::UnboundedSender<SystemCommand>,
+
+    /// Handle to the first [Arbiter] that is created with the System.
+    arbiter_handle: ArbiterHandle,
+}
+
+#[cfg(not(feature = "io-uring"))]
+impl System {
+    /// Create a new system.
+    ///
+    /// # Panics
+    /// Panics if underlying Tokio runtime can not be created.
+    #[allow(clippy::new_ret_no_self)]
+    pub fn new() -> SystemRunner {
+        Self::with_tokio_rt(|| {
+            crate::runtime::default_tokio_runtime()
+                .expect("Default Actix (Tokio) runtime could not be created.")
+        })
+    }
+
+    /// Create a new System using the [Tokio Runtime](tokio-runtime) returned from a closure.
+    ///
+    /// [tokio-runtime]: tokio::runtime::Runtime
+    pub fn with_tokio_rt<F>(runtime_factory: F) -> SystemRunner
+    where
+        F: FnOnce() -> tokio::runtime::Runtime,
+    {
+        let (stop_tx, stop_rx) = oneshot::channel();
+        let (sys_tx, sys_rx) = mpsc::unbounded_channel();
+
+        let rt = crate::runtime::Runtime::from(runtime_factory());
+        let sys_arbiter = rt.block_on(async { Arbiter::in_new_system() });
+        let system = System::construct(sys_tx, sys_arbiter.clone());
+
+        system
+            .tx()
+            .send(SystemCommand::RegisterArbiter(usize::MAX, sys_arbiter))
+            .unwrap();
+
+        // init background system arbiter
+        let sys_ctrl = SystemController::new(sys_rx, stop_tx);
+        rt.spawn(sys_ctrl);
+
+        SystemRunner { rt, stop_rx }
+    }
+}
+
+#[cfg(feature = "io-uring")]
+impl System {
+    /// Create a new system.
+    ///
+    /// # Panics
+    /// Panics if underlying Tokio runtime can not be created.
+    #[allow(clippy::new_ret_no_self)]
+    pub fn new() -> SystemRunner {
+        SystemRunner
+    }
+
+    /// Create a new System using the [Tokio Runtime](tokio-runtime) returned from a closure.
+    ///
+    /// [tokio-runtime]: tokio::runtime::Runtime
+    #[doc(hidden)]
+    pub fn with_tokio_rt<F>(_: F) -> SystemRunner
+    where
+        F: FnOnce() -> tokio::runtime::Runtime,
+    {
+        unimplemented!("System::with_tokio_rt is not implemented for io-uring feature yet")
+    }
+}
+
+impl System {
+    /// Constructs new system and registers it on the current thread.
+    pub(crate) fn construct(
+        sys_tx: mpsc::UnboundedSender<SystemCommand>,
+        arbiter_handle: ArbiterHandle,
+    ) -> Self {
+        let sys = System {
+            sys_tx,
+            arbiter_handle,
+            id: SYSTEM_COUNT.fetch_add(1, Ordering::SeqCst),
+        };
+
+        System::set_current(sys.clone());
+
+        sys
+    }
+
+    /// Get current running system.
+    ///
+    /// # Panics
+    /// Panics if no system is registered on the current thread.
+    pub fn current() -> System {
+        CURRENT.with(|cell| match *cell.borrow() {
+            Some(ref sys) => sys.clone(),
+            None => panic!("System is not running"),
+        })
+    }
+
+    /// Try to get current running system.
+    ///
+    /// Returns `None` if no System has been started.
+    ///
+    /// Unlike [`current`](Self::current), this never panics.
+    pub fn try_current() -> Option<System> {
+        CURRENT.with(|cell| cell.borrow().clone())
+    }
+
+    /// Get handle to a the System's initial [Arbiter].
+    pub fn arbiter(&self) -> &ArbiterHandle {
+        &self.arbiter_handle
+    }
+
+    /// Check if there is a System registered on the current thread.
+    pub fn is_registered() -> bool {
+        CURRENT.with(|sys| sys.borrow().is_some())
+    }
+
+    /// Register given system on current thread.
+    #[doc(hidden)]
+    pub fn set_current(sys: System) {
+        CURRENT.with(|cell| {
+            *cell.borrow_mut() = Some(sys);
+        })
+    }
+
+    /// Numeric system identifier.
+    ///
+    /// Useful when using multiple Systems.
+    pub fn id(&self) -> usize {
+        self.id
+    }
+
+    /// Stop the system (with code 0).
+    pub fn stop(&self) {
+        self.stop_with_code(0)
+    }
+
+    /// Stop the system with a given exit code.
+    pub fn stop_with_code(&self, code: i32) {
+        let _ = self.sys_tx.send(SystemCommand::Exit(code));
+    }
+
+    pub(crate) fn tx(&self) -> &mpsc::UnboundedSender<SystemCommand> {
+        &self.sys_tx
+    }
+}
+
+/// Runner that keeps a [System]'s event loop alive until stop message is received.
+#[cfg(not(feature = "io-uring"))]
+#[must_use = "A SystemRunner does nothing unless `run` is called."]
+#[derive(Debug)]
+pub struct SystemRunner {
+    rt: crate::runtime::Runtime,
+    stop_rx: oneshot::Receiver<i32>,
+}
+
+#[cfg(not(feature = "io-uring"))]
+impl SystemRunner {
+    /// Starts event loop and will return once [System] is [stopped](System::stop).
+    pub fn run(self) -> io::Result<()> {
+        let exit_code = self.run_with_code()?;
+
+        match exit_code {
+            0 => Ok(()),
+            nonzero => Err(io::Error::new(
+                io::ErrorKind::Other,
+                format!("Non-zero exit code: {}", nonzero),
+            )),
+        }
+    }
+
+    /// Runs the event loop until [stopped](System::stop_with_code), returning the exit code.
+    pub fn run_with_code(self) -> io::Result<i32> {
+        let SystemRunner { rt, stop_rx, .. } = self;
+
+        // run loop
+        rt.block_on(stop_rx)
+            .map_err(|err| io::Error::new(io::ErrorKind::Other, err))
+    }
+
+    /// Retrieves a reference to the underlying [Actix runtime](crate::Runtime) associated with this
+    /// `SystemRunner` instance.
+    ///
+    /// The Actix runtime is responsible for managing the event loop for an Actix system and
+    /// executing asynchronous tasks. This method provides access to the runtime, allowing direct
+    /// interaction with its features.
+    ///
+    /// In a typical use case, you might need to share the same runtime between different
+    /// parts of your project. For example, some components might require a [`Runtime`] to spawn
+    /// tasks on the same runtime.
+    ///
+    /// Read more in the documentation for [`Runtime`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let system_runner = actix_rt::System::new();
+    /// let actix_runtime = system_runner.runtime();
+    ///
+    /// // Use the runtime to spawn an async task or perform other operations
+    /// ```
+    ///
+    /// # Note
+    ///
+    /// While this method provides an immutable reference to the Actix runtime, which is safe to
+    /// share across threads, be aware that spawning blocking tasks on the Actix runtime could
+    /// potentially impact system performance. This is because the Actix runtime is responsible for
+    /// driving the system, and blocking tasks could delay other tasks in the run loop.
+    ///
+    /// [`Runtime`]: crate::Runtime
+    pub fn runtime(&self) -> &crate::runtime::Runtime {
+        &self.rt
+    }
+
+    /// Runs the provided future, blocking the current thread until the future completes.
+    #[track_caller]
+    #[inline]
+    pub fn block_on<F: Future>(&self, fut: F) -> F::Output {
+        self.rt.block_on(fut)
+    }
+}
+
+/// Runner that keeps a [System]'s event loop alive until stop message is received.
+#[cfg(feature = "io-uring")]
+#[must_use = "A SystemRunner does nothing unless `run` is called."]
+#[derive(Debug)]
+pub struct SystemRunner;
+
+#[cfg(feature = "io-uring")]
+impl SystemRunner {
+    /// Starts event loop and will return once [System] is [stopped](System::stop).
+    pub fn run(self) -> io::Result<()> {
+        unimplemented!("SystemRunner::run is not implemented for io-uring feature yet");
+    }
+
+    /// Runs the event loop until [stopped](System::stop_with_code), returning the exit code.
+    pub fn run_with_code(self) -> io::Result<i32> {
+        unimplemented!("SystemRunner::run_with_code is not implemented for io-uring feature yet");
+    }
+
+    /// Runs the provided future, blocking the current thread until the future completes.
+    #[inline]
+    pub fn block_on<F: Future>(&self, fut: F) -> F::Output {
+        tokio_uring::start(async move {
+            let (stop_tx, stop_rx) = oneshot::channel();
+            let (sys_tx, sys_rx) = mpsc::unbounded_channel();
+
+            let sys_arbiter = Arbiter::in_new_system();
+            let system = System::construct(sys_tx, sys_arbiter.clone());
+
+            system
+                .tx()
+                .send(SystemCommand::RegisterArbiter(usize::MAX, sys_arbiter))
+                .unwrap();
+
+            // init background system arbiter
+            let sys_ctrl = SystemController::new(sys_rx, stop_tx);
+            tokio_uring::spawn(sys_ctrl);
+
+            let res = fut.await;
+            drop(stop_rx);
+            res
+        })
+    }
+}
+
+#[derive(Debug)]
+pub(crate) enum SystemCommand {
+    Exit(i32),
+    RegisterArbiter(usize, ArbiterHandle),
+    DeregisterArbiter(usize),
+}
+
+/// There is one `SystemController` per [System]. It runs in the background, keeping track of
+/// [Arbiter]s and is able to distribute a system-wide stop command.
+#[derive(Debug)]
+pub(crate) struct SystemController {
+    stop_tx: Option<oneshot::Sender<i32>>,
+    cmd_rx: mpsc::UnboundedReceiver<SystemCommand>,
+    arbiters: HashMap<usize, ArbiterHandle>,
+}
+
+impl SystemController {
+    pub(crate) fn new(
+        cmd_rx: mpsc::UnboundedReceiver<SystemCommand>,
+        stop_tx: oneshot::Sender<i32>,
+    ) -> Self {
+        SystemController {
+            cmd_rx,
+            stop_tx: Some(stop_tx),
+            arbiters: HashMap::with_capacity(4),
+        }
+    }
+}
+
+impl Future for SystemController {
+    type Output = ();
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        // process all items currently buffered in channel
+        loop {
+            match ready!(self.cmd_rx.poll_recv(cx)) {
+                // channel closed; no more messages can be received
+                None => return Poll::Ready(()),
+
+                // process system command
+                Some(cmd) => match cmd {
+                    SystemCommand::Exit(code) => {
+                        // stop all arbiters
+                        for arb in self.arbiters.values() {
+                            arb.stop();
+                        }
+
+                        // stop event loop
+                        // will only fire once
+                        if let Some(stop_tx) = self.stop_tx.take() {
+                            let _ = stop_tx.send(code);
+                        }
+                    }
+
+                    SystemCommand::RegisterArbiter(id, arb) => {
+                        self.arbiters.insert(id, arb);
+                    }
+
+                    SystemCommand::DeregisterArbiter(id) => {
+                        self.arbiters.remove(&id);
+                    }
+                },
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/accept.rs.html b/src/actix_server/accept.rs.html new file mode 100644 index 00000000..f8c0a9d1 --- /dev/null +++ b/src/actix_server/accept.rs.html @@ -0,0 +1,925 @@ +accept.rs - source

actix_server/
accept.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
use std::{io, thread, time::Duration};
+
+use actix_rt::time::Instant;
+use mio::{Interest, Poll, Token as MioToken};
+use tracing::{debug, error, info};
+
+use crate::{
+    availability::Availability,
+    socket::MioListener,
+    waker_queue::{WakerInterest, WakerQueue, WAKER_TOKEN},
+    worker::{Conn, ServerWorker, WorkerHandleAccept, WorkerHandleServer},
+    ServerBuilder, ServerHandle,
+};
+
+const TIMEOUT_DURATION_ON_ERROR: Duration = Duration::from_millis(510);
+
+struct ServerSocketInfo {
+    token: usize,
+
+    lst: MioListener,
+
+    /// Timeout is used to mark the deadline when this socket's listener should be registered again
+    /// after an error.
+    timeout: Option<actix_rt::time::Instant>,
+}
+
+/// Poll instance of the server.
+pub(crate) struct Accept {
+    poll: Poll,
+    waker_queue: WakerQueue,
+    handles: Vec<WorkerHandleAccept>,
+    srv: ServerHandle,
+    next: usize,
+    avail: Availability,
+    /// use the smallest duration from sockets timeout.
+    timeout: Option<Duration>,
+    paused: bool,
+}
+
+impl Accept {
+    pub(crate) fn start(
+        sockets: Vec<(usize, MioListener)>,
+        builder: &ServerBuilder,
+    ) -> io::Result<(WakerQueue, Vec<WorkerHandleServer>, thread::JoinHandle<()>)> {
+        let handle_server = ServerHandle::new(builder.cmd_tx.clone());
+
+        // construct poll instance and its waker
+        let poll = Poll::new()?;
+        let waker_queue = WakerQueue::new(poll.registry())?;
+
+        // start workers and collect handles
+        let (handles_accept, handles_server) = (0..builder.threads)
+            .map(|idx| {
+                // clone service factories
+                let factories = builder
+                    .factories
+                    .iter()
+                    .map(|f| f.clone_factory())
+                    .collect::<Vec<_>>();
+
+                // start worker using service factories
+                ServerWorker::start(idx, factories, waker_queue.clone(), builder.worker_config)
+            })
+            .collect::<io::Result<Vec<_>>>()?
+            .into_iter()
+            .unzip();
+
+        let (mut accept, mut sockets) = Accept::new_with_sockets(
+            poll,
+            waker_queue.clone(),
+            sockets,
+            handles_accept,
+            handle_server,
+        )?;
+
+        let accept_handle = thread::Builder::new()
+            .name("actix-server acceptor".to_owned())
+            .spawn(move || accept.poll_with(&mut sockets))
+            .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
+
+        Ok((waker_queue, handles_server, accept_handle))
+    }
+
+    fn new_with_sockets(
+        poll: Poll,
+        waker_queue: WakerQueue,
+        sockets: Vec<(usize, MioListener)>,
+        accept_handles: Vec<WorkerHandleAccept>,
+        server_handle: ServerHandle,
+    ) -> io::Result<(Accept, Box<[ServerSocketInfo]>)> {
+        let sockets = sockets
+            .into_iter()
+            .map(|(token, mut lst)| {
+                // Start listening for incoming connections
+                poll.registry()
+                    .register(&mut lst, MioToken(token), Interest::READABLE)?;
+
+                Ok(ServerSocketInfo {
+                    token,
+                    lst,
+                    timeout: None,
+                })
+            })
+            .collect::<io::Result<_>>()?;
+
+        let mut avail = Availability::default();
+
+        // Assume all handles are avail at construct time.
+        avail.set_available_all(&accept_handles);
+
+        let accept = Accept {
+            poll,
+            waker_queue,
+            handles: accept_handles,
+            srv: server_handle,
+            next: 0,
+            avail,
+            timeout: None,
+            paused: false,
+        };
+
+        Ok((accept, sockets))
+    }
+
+    /// blocking wait for readiness events triggered by mio
+    fn poll_with(&mut self, sockets: &mut [ServerSocketInfo]) {
+        let mut events = mio::Events::with_capacity(256);
+
+        loop {
+            if let Err(err) = self.poll.poll(&mut events, self.timeout) {
+                match err.kind() {
+                    io::ErrorKind::Interrupted => {}
+                    _ => panic!("Poll error: {}", err),
+                }
+            }
+
+            for event in events.iter() {
+                let token = event.token();
+                match token {
+                    WAKER_TOKEN => {
+                        let exit = self.handle_waker(sockets);
+                        if exit {
+                            info!("accept thread stopped");
+                            return;
+                        }
+                    }
+                    _ => {
+                        let token = usize::from(token);
+                        self.accept(sockets, token);
+                    }
+                }
+            }
+
+            // check for timeout and re-register sockets
+            self.process_timeout(sockets);
+        }
+    }
+
+    fn handle_waker(&mut self, sockets: &mut [ServerSocketInfo]) -> bool {
+        // This is a loop because interests for command from previous version was
+        // a loop that would try to drain the command channel. It's yet unknown
+        // if it's necessary/good practice to actively drain the waker queue.
+        loop {
+            // Take guard with every iteration so no new interests can be added until the current
+            // task is done. Take care not to take the guard again inside this loop.
+            let mut guard = self.waker_queue.guard();
+
+            #[allow(clippy::significant_drop_in_scrutinee)]
+            match guard.pop_front() {
+                // Worker notified it became available.
+                Some(WakerInterest::WorkerAvailable(idx)) => {
+                    drop(guard);
+
+                    self.avail.set_available(idx, true);
+
+                    if !self.paused {
+                        self.accept_all(sockets);
+                    }
+                }
+
+                // A new worker thread has been created so store its handle.
+                Some(WakerInterest::Worker(handle)) => {
+                    drop(guard);
+
+                    self.avail.set_available(handle.idx(), true);
+                    self.handles.push(handle);
+
+                    if !self.paused {
+                        self.accept_all(sockets);
+                    }
+                }
+
+                Some(WakerInterest::Pause) => {
+                    drop(guard);
+
+                    if !self.paused {
+                        self.paused = true;
+
+                        self.deregister_all(sockets);
+                    }
+                }
+
+                Some(WakerInterest::Resume) => {
+                    drop(guard);
+
+                    if self.paused {
+                        self.paused = false;
+
+                        sockets.iter_mut().for_each(|info| {
+                            self.register_logged(info);
+                        });
+
+                        self.accept_all(sockets);
+                    }
+                }
+
+                Some(WakerInterest::Stop) => {
+                    if !self.paused {
+                        self.deregister_all(sockets);
+                    }
+
+                    return true;
+                }
+
+                // waker queue is drained
+                None => {
+                    // Reset the WakerQueue before break so it does not grow infinitely
+                    WakerQueue::reset(&mut guard);
+
+                    return false;
+                }
+            }
+        }
+    }
+
+    fn process_timeout(&mut self, sockets: &mut [ServerSocketInfo]) {
+        // always remove old timeouts
+        if self.timeout.take().is_some() {
+            let now = Instant::now();
+
+            sockets
+                .iter_mut()
+                // Only sockets that had an associated timeout were deregistered.
+                .filter(|info| info.timeout.is_some())
+                .for_each(|info| {
+                    let inst = info.timeout.take().unwrap();
+
+                    if now < inst {
+                        // still timed out; try to set new timeout
+                        info.timeout = Some(inst);
+                        self.set_timeout(inst - now);
+                    } else if !self.paused {
+                        // timeout expired; register socket again
+                        self.register_logged(info);
+                    }
+
+                    // Drop the timeout if server is paused and socket timeout is expired.
+                    // When server recovers from pause it will register all sockets without
+                    // a timeout value so this socket register will be delayed till then.
+                });
+        }
+    }
+
+    /// Update accept timeout with `duration` if it is shorter than current timeout.
+    fn set_timeout(&mut self, duration: Duration) {
+        match self.timeout {
+            Some(ref mut timeout) => {
+                if *timeout > duration {
+                    *timeout = duration;
+                }
+            }
+            None => self.timeout = Some(duration),
+        }
+    }
+
+    #[cfg(not(target_os = "windows"))]
+    fn register(&self, info: &mut ServerSocketInfo) -> io::Result<()> {
+        let token = MioToken(info.token);
+        self.poll
+            .registry()
+            .register(&mut info.lst, token, Interest::READABLE)
+    }
+
+    #[cfg(target_os = "windows")]
+    fn register(&self, info: &mut ServerSocketInfo) -> io::Result<()> {
+        // On windows, calling register without deregister cause an error.
+        // See https://github.com/actix/actix-web/issues/905
+        // Calling reregister seems to fix the issue.
+        let token = MioToken(info.token);
+        self.poll
+            .registry()
+            .register(&mut info.lst, token, Interest::READABLE)
+            .or_else(|_| {
+                self.poll
+                    .registry()
+                    .reregister(&mut info.lst, token, Interest::READABLE)
+            })
+    }
+
+    fn register_logged(&self, info: &mut ServerSocketInfo) {
+        match self.register(info) {
+            Ok(_) => debug!("resume accepting connections on {}", info.lst.local_addr()),
+            Err(err) => error!("can not register server socket {}", err),
+        }
+    }
+
+    fn deregister_logged(&self, info: &mut ServerSocketInfo) {
+        match self.poll.registry().deregister(&mut info.lst) {
+            Ok(_) => debug!("paused accepting connections on {}", info.lst.local_addr()),
+            Err(err) => {
+                error!("can not deregister server socket {}", err)
+            }
+        }
+    }
+
+    fn deregister_all(&self, sockets: &mut [ServerSocketInfo]) {
+        // This is a best effort implementation with following limitation:
+        //
+        // Every ServerSocketInfo with associated timeout will be skipped and it's timeout is
+        // removed in the process.
+        //
+        // Therefore WakerInterest::Pause followed by WakerInterest::Resume in a very short gap
+        // (less than 500ms) would cause all timing out ServerSocketInfos be re-registered before
+        // expected timing.
+        sockets
+            .iter_mut()
+            // Take all timeout.
+            // This is to prevent Accept::process_timer method re-register a socket afterwards.
+            .map(|info| (info.timeout.take(), info))
+            // Socket info with a timeout is already deregistered so skip them.
+            .filter(|(timeout, _)| timeout.is_none())
+            .for_each(|(_, info)| self.deregister_logged(info));
+    }
+
+    // Send connection to worker and handle error.
+    fn send_connection(&mut self, conn: Conn) -> Result<(), Conn> {
+        let next = self.next();
+        match next.send(conn) {
+            Ok(_) => {
+                // Increment counter of WorkerHandle.
+                // Set worker to unavailable with it hit max (Return false).
+                if !next.inc_counter() {
+                    let idx = next.idx();
+                    self.avail.set_available(idx, false);
+                }
+                self.set_next();
+                Ok(())
+            }
+            Err(conn) => {
+                // Worker thread is error and could be gone.
+                // Remove worker handle and notify `ServerBuilder`.
+                self.remove_next();
+
+                if self.handles.is_empty() {
+                    error!("no workers");
+                    // All workers are gone and Conn is nowhere to be sent.
+                    // Treat this situation as Ok and drop Conn.
+                    return Ok(());
+                } else if self.handles.len() <= self.next {
+                    self.next = 0;
+                }
+
+                Err(conn)
+            }
+        }
+    }
+
+    fn accept_one(&mut self, mut conn: Conn) {
+        loop {
+            let next = self.next();
+            let idx = next.idx();
+
+            if self.avail.get_available(idx) {
+                match self.send_connection(conn) {
+                    Ok(_) => return,
+                    Err(c) => conn = c,
+                }
+            } else {
+                self.avail.set_available(idx, false);
+                self.set_next();
+
+                if !self.avail.available() {
+                    while let Err(c) = self.send_connection(conn) {
+                        conn = c;
+                    }
+                    return;
+                }
+            }
+        }
+    }
+
+    fn accept(&mut self, sockets: &mut [ServerSocketInfo], token: usize) {
+        while self.avail.available() {
+            let info = &mut sockets[token];
+
+            match info.lst.accept() {
+                Ok(io) => {
+                    let conn = Conn { io, token };
+                    self.accept_one(conn);
+                }
+                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => return,
+                Err(ref err) if connection_error(err) => continue,
+                Err(err) => {
+                    error!("error accepting connection: {}", err);
+
+                    // deregister listener temporary
+                    self.deregister_logged(info);
+
+                    // sleep after error. write the timeout to socket info as later
+                    // the poll would need it mark which socket and when it's
+                    // listener should be registered
+                    info.timeout = Some(Instant::now() + Duration::from_millis(500));
+                    self.set_timeout(TIMEOUT_DURATION_ON_ERROR);
+
+                    return;
+                }
+            };
+        }
+    }
+
+    fn accept_all(&mut self, sockets: &mut [ServerSocketInfo]) {
+        sockets
+            .iter_mut()
+            .map(|info| info.token)
+            .collect::<Vec<_>>()
+            .into_iter()
+            .for_each(|idx| self.accept(sockets, idx))
+    }
+
+    #[inline(always)]
+    fn next(&self) -> &WorkerHandleAccept {
+        &self.handles[self.next]
+    }
+
+    /// Set next worker handle that would accept connection.
+    #[inline(always)]
+    fn set_next(&mut self) {
+        self.next = (self.next + 1) % self.handles.len();
+    }
+
+    /// Remove next worker handle that fail to accept connection.
+    fn remove_next(&mut self) {
+        let handle = self.handles.swap_remove(self.next);
+        let idx = handle.idx();
+        // A message is sent to `ServerBuilder` future to notify it a new worker
+        // should be made.
+        self.srv.worker_faulted(idx);
+        self.avail.set_available(idx, false);
+    }
+}
+
+/// This function defines errors that are per-connection; if we get this error from the `accept()`
+/// system call it means the next connection might be ready to be accepted.
+///
+/// All other errors will incur a timeout before next `accept()` call is attempted. The timeout is
+/// useful to handle resource exhaustion errors like `ENFILE` and `EMFILE`. Otherwise, it could
+/// enter into a temporary spin loop.
+fn connection_error(e: &io::Error) -> bool {
+    e.kind() == io::ErrorKind::ConnectionRefused
+        || e.kind() == io::ErrorKind::ConnectionAborted
+        || e.kind() == io::ErrorKind::ConnectionReset
+}
+
\ No newline at end of file diff --git a/src/actix_server/availability.rs.html b/src/actix_server/availability.rs.html new file mode 100644 index 00000000..3053529f --- /dev/null +++ b/src/actix_server/availability.rs.html @@ -0,0 +1,243 @@ +availability.rs - source

actix_server/
availability.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
use crate::worker::WorkerHandleAccept;
+
+/// Array of u128 with every bit as marker for a worker handle's availability.
+#[derive(Debug, Default)]
+pub(crate) struct Availability([u128; 4]);
+
+impl Availability {
+    /// Check if any worker handle is available
+    #[inline(always)]
+    pub(crate) fn available(&self) -> bool {
+        self.0.iter().any(|a| *a != 0)
+    }
+
+    /// Check if worker handle is available by index
+    #[inline(always)]
+    pub(crate) fn get_available(&self, idx: usize) -> bool {
+        let (offset, idx) = Self::offset(idx);
+
+        self.0[offset] & (1 << idx as u128) != 0
+    }
+
+    /// Set worker handle available state by index.
+    pub(crate) fn set_available(&mut self, idx: usize, avail: bool) {
+        let (offset, idx) = Self::offset(idx);
+
+        let off = 1 << idx as u128;
+        if avail {
+            self.0[offset] |= off;
+        } else {
+            self.0[offset] &= !off
+        }
+    }
+
+    /// Set all worker handle to available state.
+    /// This would result in a re-check on all workers' availability.
+    pub(crate) fn set_available_all(&mut self, handles: &[WorkerHandleAccept]) {
+        handles.iter().for_each(|handle| {
+            self.set_available(handle.idx(), true);
+        })
+    }
+
+    /// Get offset and adjusted index of given worker handle index.
+    pub(crate) fn offset(idx: usize) -> (usize, usize) {
+        if idx < 128 {
+            (0, idx)
+        } else if idx < 128 * 2 {
+            (1, idx - 128)
+        } else if idx < 128 * 3 {
+            (2, idx - 128 * 2)
+        } else if idx < 128 * 4 {
+            (3, idx - 128 * 3)
+        } else {
+            panic!("Max WorkerHandle count is 512")
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn single(aval: &mut Availability, idx: usize) {
+        aval.set_available(idx, true);
+        assert!(aval.available());
+
+        aval.set_available(idx, true);
+
+        aval.set_available(idx, false);
+        assert!(!aval.available());
+
+        aval.set_available(idx, false);
+        assert!(!aval.available());
+    }
+
+    fn multi(aval: &mut Availability, mut idx: Vec<usize>) {
+        idx.iter().for_each(|idx| aval.set_available(*idx, true));
+
+        assert!(aval.available());
+
+        while let Some(idx) = idx.pop() {
+            assert!(aval.available());
+            aval.set_available(idx, false);
+        }
+
+        assert!(!aval.available());
+    }
+
+    #[test]
+    fn availability() {
+        let mut aval = Availability::default();
+
+        single(&mut aval, 1);
+        single(&mut aval, 128);
+        single(&mut aval, 256);
+        single(&mut aval, 511);
+
+        let idx = (0..511).filter(|i| i % 3 == 0 && i % 5 == 0).collect();
+
+        multi(&mut aval, idx);
+
+        multi(&mut aval, (0..511).collect())
+    }
+
+    #[test]
+    #[should_panic]
+    fn overflow() {
+        let mut aval = Availability::default();
+        single(&mut aval, 512);
+    }
+
+    #[test]
+    fn pin_point() {
+        let mut aval = Availability::default();
+
+        aval.set_available(438, true);
+
+        aval.set_available(479, true);
+
+        assert_eq!(aval.0[3], 1 << (438 - 384) | 1 << (479 - 384));
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/builder.rs.html b/src/actix_server/builder.rs.html new file mode 100644 index 00000000..d5a38f41 --- /dev/null +++ b/src/actix_server/builder.rs.html @@ -0,0 +1,757 @@ +builder.rs - source

actix_server/
builder.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
use std::{io, num::NonZeroUsize, time::Duration};
+
+use actix_rt::net::TcpStream;
+use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
+
+use crate::{
+    server::ServerCommand,
+    service::{InternalServiceFactory, ServerServiceFactory, StreamNewService},
+    socket::{create_mio_tcp_listener, MioListener, MioTcpListener, StdTcpListener, ToSocketAddrs},
+    worker::ServerWorkerConfig,
+    Server,
+};
+
+/// Multipath TCP (MPTCP) preference.
+///
+/// Currently only useful on Linux.
+///
+#[cfg_attr(target_os = "linux", doc = "Also see [`ServerBuilder::mptcp()`].")]
+#[derive(Debug, Clone)]
+pub enum MpTcp {
+    /// MPTCP will not be used when binding sockets.
+    Disabled,
+
+    /// MPTCP will be attempted when binding sockets. If errors occur, regular TCP will be
+    /// attempted, too.
+    TcpFallback,
+
+    /// MPTCP will be used when binding sockets (with no fallback).
+    NoFallback,
+}
+
+/// [Server] builder.
+pub struct ServerBuilder {
+    pub(crate) threads: usize,
+    pub(crate) token: usize,
+    pub(crate) backlog: u32,
+    pub(crate) factories: Vec<Box<dyn InternalServiceFactory>>,
+    pub(crate) sockets: Vec<(usize, String, MioListener)>,
+    pub(crate) mptcp: MpTcp,
+    pub(crate) exit: bool,
+    pub(crate) listen_os_signals: bool,
+    pub(crate) cmd_tx: UnboundedSender<ServerCommand>,
+    pub(crate) cmd_rx: UnboundedReceiver<ServerCommand>,
+    pub(crate) worker_config: ServerWorkerConfig,
+}
+
+impl Default for ServerBuilder {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl ServerBuilder {
+    /// Create new Server builder instance
+    pub fn new() -> ServerBuilder {
+        let (cmd_tx, cmd_rx) = unbounded_channel();
+
+        ServerBuilder {
+            threads: std::thread::available_parallelism().map_or(2, NonZeroUsize::get),
+            token: 0,
+            factories: Vec::new(),
+            sockets: Vec::new(),
+            backlog: 2048,
+            mptcp: MpTcp::Disabled,
+            exit: false,
+            listen_os_signals: true,
+            cmd_tx,
+            cmd_rx,
+            worker_config: ServerWorkerConfig::default(),
+        }
+    }
+
+    /// Sets number of workers to start.
+    ///
+    /// See [`bind()`](Self::bind()) for more details on how worker count affects the number of
+    /// server factory instantiations.
+    ///
+    /// The default worker count is the determined by [`std::thread::available_parallelism()`]. See
+    /// its documentation to determine what behavior you should expect when server is run.
+    ///
+    /// `num` must be greater than 0.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `num` is 0.
+    pub fn workers(mut self, num: usize) -> Self {
+        assert_ne!(num, 0, "workers must be greater than 0");
+        self.threads = num;
+        self
+    }
+
+    /// Set max number of threads for each worker's blocking task thread pool.
+    ///
+    /// One thread pool is set up **per worker**; not shared across workers.
+    ///
+    /// # Examples:
+    /// ```
+    /// # use actix_server::ServerBuilder;
+    /// let builder = ServerBuilder::new()
+    ///     .workers(4) // server has 4 worker thread.
+    ///     .worker_max_blocking_threads(4); // every worker has 4 max blocking threads.
+    /// ```
+    ///
+    /// See [tokio::runtime::Builder::max_blocking_threads] for behavior reference.
+    pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
+        self.worker_config.max_blocking_threads(num);
+        self
+    }
+
+    /// Set the maximum number of pending connections.
+    ///
+    /// This refers to the number of clients that can be waiting to be served. Exceeding this number
+    /// results in the client getting an error when attempting to connect. It should only affect
+    /// servers under significant load.
+    ///
+    /// Generally set in the 64-2048 range. Default value is 2048.
+    ///
+    /// This method should be called before `bind()` method call.
+    pub fn backlog(mut self, num: u32) -> Self {
+        self.backlog = num;
+        self
+    }
+
+    /// Sets MultiPath TCP (MPTCP) preference on bound sockets.
+    ///
+    /// Multipath TCP (MPTCP) builds on top of TCP to improve connection redundancy and performance
+    /// by sharing a network data stream across multiple underlying TCP sessions. See [mptcp.dev]
+    /// for more info about MPTCP itself.
+    ///
+    /// MPTCP is available on Linux kernel version 5.6 and higher. In addition, you'll also need to
+    /// ensure the kernel option is enabled using `sysctl net.mptcp.enabled=1`.
+    ///
+    /// This method will have no effect if called after a `bind()`.
+    ///
+    /// [mptcp.dev]: https://www.mptcp.dev
+    #[cfg(target_os = "linux")]
+    pub fn mptcp(mut self, mptcp_enabled: MpTcp) -> Self {
+        self.mptcp = mptcp_enabled;
+        self
+    }
+
+    /// Sets the maximum per-worker number of concurrent connections.
+    ///
+    /// All socket listeners will stop accepting connections when this limit is reached for
+    /// each worker.
+    ///
+    /// By default max connections is set to a 25k per worker.
+    pub fn max_concurrent_connections(mut self, num: usize) -> Self {
+        self.worker_config.max_concurrent_connections(num);
+        self
+    }
+
+    #[doc(hidden)]
+    #[deprecated(since = "2.0.0", note = "Renamed to `max_concurrent_connections`.")]
+    pub fn maxconn(self, num: usize) -> Self {
+        self.max_concurrent_connections(num)
+    }
+
+    /// Sets flag to stop Actix `System` after server shutdown.
+    ///
+    /// This has no effect when server is running in a Tokio-only runtime.
+    pub fn system_exit(mut self) -> Self {
+        self.exit = true;
+        self
+    }
+
+    /// Disables OS signal handling.
+    pub fn disable_signals(mut self) -> Self {
+        self.listen_os_signals = false;
+        self
+    }
+
+    /// Timeout for graceful workers shutdown in seconds.
+    ///
+    /// After receiving a stop signal, workers have this much time to finish serving requests.
+    /// Workers still alive after the timeout are force dropped.
+    ///
+    /// By default shutdown timeout sets to 30 seconds.
+    pub fn shutdown_timeout(mut self, sec: u64) -> Self {
+        self.worker_config
+            .shutdown_timeout(Duration::from_secs(sec));
+        self
+    }
+
+    /// Adds new service to the server.
+    ///
+    /// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.
+    ///
+    /// # Worker Count
+    ///
+    /// The `factory` will be instantiated multiple times in most scenarios. The number of
+    /// instantiations is number of [`workers`](Self::workers()) × number of sockets resolved by
+    /// `addrs`.
+    ///
+    /// For example, if you've manually set [`workers`](Self::workers()) to 2, and use `127.0.0.1`
+    /// as the bind `addrs`, then `factory` will be instantiated twice. However, using `localhost`
+    /// as the bind `addrs` can often resolve to both `127.0.0.1` (IPv4) _and_ `::1` (IPv6), causing
+    /// the `factory` to be instantiated 4 times (2 workers × 2 bind addresses).
+    ///
+    /// Using a bind address of `0.0.0.0`, which signals to use all interfaces, may also multiple
+    /// the number of instantiations in a similar way.
+    ///
+    /// # Errors
+    ///
+    /// Returns an `io::Error` if:
+    /// - `addrs` cannot be resolved into one or more socket addresses;
+    /// - all the resolved socket addresses are already bound.
+    pub fn bind<F, U, N>(mut self, name: N, addrs: U, factory: F) -> io::Result<Self>
+    where
+        F: ServerServiceFactory<TcpStream>,
+        U: ToSocketAddrs,
+        N: AsRef<str>,
+    {
+        let sockets = bind_addr(addrs, self.backlog, &self.mptcp)?;
+
+        tracing::trace!("binding server to: {sockets:?}");
+
+        for lst in sockets {
+            let token = self.next_token();
+
+            self.factories.push(StreamNewService::create(
+                name.as_ref().to_string(),
+                token,
+                factory.clone(),
+                lst.local_addr()?,
+            ));
+
+            self.sockets
+                .push((token, name.as_ref().to_string(), MioListener::Tcp(lst)));
+        }
+
+        Ok(self)
+    }
+
+    /// Adds service to the server using a socket listener already bound.
+    ///
+    /// # Worker Count
+    ///
+    /// The `factory` will be instantiated multiple times in most scenarios. The number of
+    /// instantiations is: number of [`workers`](Self::workers()).
+    pub fn listen<F, N: AsRef<str>>(
+        mut self,
+        name: N,
+        lst: StdTcpListener,
+        factory: F,
+    ) -> io::Result<Self>
+    where
+        F: ServerServiceFactory<TcpStream>,
+    {
+        lst.set_nonblocking(true)?;
+        let addr = lst.local_addr()?;
+
+        let token = self.next_token();
+        self.factories.push(StreamNewService::create(
+            name.as_ref().to_string(),
+            token,
+            factory,
+            addr,
+        ));
+
+        self.sockets
+            .push((token, name.as_ref().to_string(), MioListener::from(lst)));
+
+        Ok(self)
+    }
+
+    /// Starts processing incoming connections and return server controller.
+    pub fn run(self) -> Server {
+        if self.sockets.is_empty() {
+            panic!("Server should have at least one bound socket");
+        } else {
+            tracing::info!("starting {} workers", self.threads);
+            Server::new(self)
+        }
+    }
+
+    fn next_token(&mut self) -> usize {
+        let token = self.token;
+        self.token += 1;
+        token
+    }
+}
+
+#[cfg(unix)]
+impl ServerBuilder {
+    /// Adds new service to the server using a UDS (unix domain socket) address.
+    ///
+    /// # Worker Count
+    ///
+    /// The `factory` will be instantiated multiple times in most scenarios. The number of
+    /// instantiations is: number of [`workers`](Self::workers()).
+    pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
+    where
+        F: ServerServiceFactory<actix_rt::net::UnixStream>,
+        N: AsRef<str>,
+        U: AsRef<std::path::Path>,
+    {
+        // The path must not exist when we try to bind.
+        // Try to remove it to avoid bind error.
+        if let Err(err) = std::fs::remove_file(addr.as_ref()) {
+            // NotFound is expected and not an issue. Anything else is.
+            if err.kind() != std::io::ErrorKind::NotFound {
+                return Err(err);
+            }
+        }
+
+        let lst = crate::socket::StdUnixListener::bind(addr)?;
+        self.listen_uds(name, lst, factory)
+    }
+
+    /// Adds new service to the server using a UDS (unix domain socket) listener already bound.
+    ///
+    /// Useful when running as a systemd service and a socket FD is acquired externally.
+    ///
+    /// # Worker Count
+    ///
+    /// The `factory` will be instantiated multiple times in most scenarios. The number of
+    /// instantiations is: number of [`workers`](Self::workers()).
+    pub fn listen_uds<F, N: AsRef<str>>(
+        mut self,
+        name: N,
+        lst: crate::socket::StdUnixListener,
+        factory: F,
+    ) -> io::Result<Self>
+    where
+        F: ServerServiceFactory<actix_rt::net::UnixStream>,
+    {
+        use std::net::{IpAddr, Ipv4Addr};
+
+        lst.set_nonblocking(true)?;
+
+        let token = self.next_token();
+        let addr = crate::socket::StdSocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+
+        self.factories.push(StreamNewService::create(
+            name.as_ref().to_string(),
+            token,
+            factory,
+            addr,
+        ));
+
+        self.sockets
+            .push((token, name.as_ref().to_string(), MioListener::from(lst)));
+
+        Ok(self)
+    }
+}
+
+pub(super) fn bind_addr<S: ToSocketAddrs>(
+    addr: S,
+    backlog: u32,
+    mptcp: &MpTcp,
+) -> io::Result<Vec<MioTcpListener>> {
+    let mut opt_err = None;
+    let mut success = false;
+    let mut sockets = Vec::new();
+
+    for addr in addr.to_socket_addrs()? {
+        match create_mio_tcp_listener(addr, backlog, mptcp) {
+            Ok(lst) => {
+                success = true;
+                sockets.push(lst);
+            }
+            Err(err) => opt_err = Some(err),
+        }
+    }
+
+    if success {
+        Ok(sockets)
+    } else if let Some(err) = opt_err.take() {
+        Err(err)
+    } else {
+        Err(io::Error::new(
+            io::ErrorKind::Other,
+            "Can not bind to address.",
+        ))
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/handle.rs.html b/src/actix_server/handle.rs.html new file mode 100644 index 00000000..fda7881b --- /dev/null +++ b/src/actix_server/handle.rs.html @@ -0,0 +1,113 @@ +handle.rs - source

actix_server/
handle.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
use std::future::Future;
+
+use tokio::sync::{mpsc::UnboundedSender, oneshot};
+
+use crate::server::ServerCommand;
+
+/// Server handle.
+#[derive(Debug, Clone)]
+pub struct ServerHandle {
+    cmd_tx: UnboundedSender<ServerCommand>,
+}
+
+impl ServerHandle {
+    pub(crate) fn new(cmd_tx: UnboundedSender<ServerCommand>) -> Self {
+        ServerHandle { cmd_tx }
+    }
+
+    pub(crate) fn worker_faulted(&self, idx: usize) {
+        let _ = self.cmd_tx.send(ServerCommand::WorkerFaulted(idx));
+    }
+
+    /// Pause accepting incoming connections.
+    ///
+    /// May drop socket pending connection. All open connections remain active.
+    pub fn pause(&self) -> impl Future<Output = ()> {
+        let (tx, rx) = oneshot::channel();
+        let _ = self.cmd_tx.send(ServerCommand::Pause(tx));
+        async {
+            let _ = rx.await;
+        }
+    }
+
+    /// Resume accepting incoming connections.
+    pub fn resume(&self) -> impl Future<Output = ()> {
+        let (tx, rx) = oneshot::channel();
+        let _ = self.cmd_tx.send(ServerCommand::Resume(tx));
+        async {
+            let _ = rx.await;
+        }
+    }
+
+    /// Stop incoming connection processing, stop all workers and exit.
+    pub fn stop(&self, graceful: bool) -> impl Future<Output = ()> {
+        let (tx, rx) = oneshot::channel();
+
+        let _ = self.cmd_tx.send(ServerCommand::Stop {
+            graceful,
+            completion: Some(tx),
+            force_system_stop: false,
+        });
+
+        async {
+            let _ = rx.await;
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/join_all.rs.html b/src/actix_server/join_all.rs.html new file mode 100644 index 00000000..b5fb8a36 --- /dev/null +++ b/src/actix_server/join_all.rs.html @@ -0,0 +1,157 @@ +join_all.rs - source

actix_server/
join_all.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
use std::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use futures_core::future::BoxFuture;
+
+// a poor man's join future. joined future is only used when starting/stopping the server.
+// pin_project and pinned futures are overkill for this task.
+pub(crate) struct JoinAll<T> {
+    fut: Vec<JoinFuture<T>>,
+}
+
+pub(crate) fn join_all<T>(fut: Vec<impl Future<Output = T> + Send + 'static>) -> JoinAll<T> {
+    let fut = fut
+        .into_iter()
+        .map(|f| JoinFuture::Future(Box::pin(f)))
+        .collect();
+
+    JoinAll { fut }
+}
+
+enum JoinFuture<T> {
+    Future(BoxFuture<'static, T>),
+    Result(Option<T>),
+}
+
+impl<T> Unpin for JoinAll<T> {}
+
+impl<T> Future for JoinAll<T> {
+    type Output = Vec<T>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut ready = true;
+
+        let this = self.get_mut();
+        for fut in this.fut.iter_mut() {
+            if let JoinFuture::Future(f) = fut {
+                match f.as_mut().poll(cx) {
+                    Poll::Ready(t) => {
+                        *fut = JoinFuture::Result(Some(t));
+                    }
+                    Poll::Pending => ready = false,
+                }
+            }
+        }
+
+        if ready {
+            let mut res = Vec::new();
+            for fut in this.fut.iter_mut() {
+                if let JoinFuture::Result(f) = fut {
+                    res.push(f.take().unwrap());
+                }
+            }
+
+            Poll::Ready(res)
+        } else {
+            Poll::Pending
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use actix_utils::future::ready;
+
+    use super::*;
+
+    #[actix_rt::test]
+    async fn test_join_all() {
+        let futs = vec![ready(Ok(1)), ready(Err(3)), ready(Ok(9))];
+        let mut res = join_all(futs).await.into_iter();
+        assert_eq!(Ok(1), res.next().unwrap());
+        assert_eq!(Err(3), res.next().unwrap());
+        assert_eq!(Ok(9), res.next().unwrap());
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/lib.rs.html b/src/actix_server/lib.rs.html new file mode 100644 index 00000000..2d5b6617 --- /dev/null +++ b/src/actix_server/lib.rs.html @@ -0,0 +1,73 @@ +lib.rs - source

actix_server/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
//! General purpose TCP server.
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
+mod accept;
+mod availability;
+mod builder;
+mod handle;
+mod join_all;
+mod server;
+mod service;
+mod signals;
+mod socket;
+mod test_server;
+mod waker_queue;
+mod worker;
+
+#[doc(hidden)]
+pub use self::socket::FromStream;
+pub use self::{
+    builder::{MpTcp, ServerBuilder},
+    handle::ServerHandle,
+    server::Server,
+    service::ServerServiceFactory,
+    test_server::TestServer,
+};
+
+/// Start server building process
+#[doc(hidden)]
+#[deprecated(since = "2.0.0", note = "Use `Server::build()`.")]
+pub fn new() -> ServerBuilder {
+    ServerBuilder::default()
+}
+
\ No newline at end of file diff --git a/src/actix_server/server.rs.html b/src/actix_server/server.rs.html new file mode 100644 index 00000000..c4110445 --- /dev/null +++ b/src/actix_server/server.rs.html @@ -0,0 +1,737 @@ +server.rs - source

actix_server/
server.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
use std::{
+    future::Future,
+    io, mem,
+    pin::Pin,
+    task::{Context, Poll},
+    thread,
+    time::Duration,
+};
+
+use actix_rt::{time::sleep, System};
+use futures_core::{future::BoxFuture, Stream};
+use futures_util::stream::StreamExt as _;
+use tokio::sync::{mpsc::UnboundedReceiver, oneshot};
+use tracing::{error, info};
+
+use crate::{
+    accept::Accept,
+    builder::ServerBuilder,
+    join_all::join_all,
+    service::InternalServiceFactory,
+    signals::{SignalKind, Signals},
+    waker_queue::{WakerInterest, WakerQueue},
+    worker::{ServerWorker, ServerWorkerConfig, WorkerHandleServer},
+    ServerHandle,
+};
+
+#[derive(Debug)]
+pub(crate) enum ServerCommand {
+    /// Worker failed to accept connection, indicating a probable panic.
+    ///
+    /// Contains index of faulted worker.
+    WorkerFaulted(usize),
+
+    /// Pause accepting connections.
+    ///
+    /// Contains return channel to notify caller of successful state change.
+    Pause(oneshot::Sender<()>),
+
+    /// Resume accepting connections.
+    ///
+    /// Contains return channel to notify caller of successful state change.
+    Resume(oneshot::Sender<()>),
+
+    /// Stop accepting connections and begin shutdown procedure.
+    Stop {
+        /// True if shut down should be graceful.
+        graceful: bool,
+
+        /// Return channel to notify caller that shutdown is complete.
+        completion: Option<oneshot::Sender<()>>,
+
+        /// Force System exit when true, overriding `ServerBuilder::system_exit()` if it is false.
+        force_system_stop: bool,
+    },
+}
+
+/// General purpose TCP server that runs services receiving Tokio `TcpStream`s.
+///
+/// Handles creating worker threads, restarting faulted workers, connection accepting, and
+/// back-pressure logic.
+///
+/// Creates a worker per CPU core (or the number specified in [`ServerBuilder::workers`]) and
+/// distributes connections with a round-robin strategy.
+///
+/// The [Server] must be awaited or polled in order to start running. It will resolve when the
+/// server has fully shut down.
+///
+/// # Shutdown Signals
+/// On UNIX systems, `SIGTERM` will start a graceful shutdown and `SIGQUIT` or `SIGINT` will start a
+/// forced shutdown. On Windows, a Ctrl-C signal will start a forced shutdown.
+///
+/// A graceful shutdown will wait for all workers to stop first.
+///
+/// # Examples
+/// The following is a TCP echo server. Test using `telnet 127.0.0.1 8080`.
+///
+/// ```no_run
+/// use std::io;
+///
+/// use actix_rt::net::TcpStream;
+/// use actix_server::Server;
+/// use actix_service::{fn_service, ServiceFactoryExt as _};
+/// use bytes::BytesMut;
+/// use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
+///
+/// #[actix_rt::main]
+/// async fn main() -> io::Result<()> {
+///     let bind_addr = ("127.0.0.1", 8080);
+///
+///     Server::build()
+///         .bind("echo", bind_addr, move || {
+///             fn_service(move |mut stream: TcpStream| {
+///                 async move {
+///                     let mut size = 0;
+///                     let mut buf = BytesMut::new();
+///
+///                     loop {
+///                         match stream.read_buf(&mut buf).await {
+///                             // end of stream; bail from loop
+///                             Ok(0) => break,
+///
+///                             // write bytes back to stream
+///                             Ok(bytes_read) => {
+///                                 stream.write_all(&buf[size..]).await.unwrap();
+///                                 size += bytes_read;
+///                             }
+///
+///                             Err(err) => {
+///                                 eprintln!("Stream Error: {:?}", err);
+///                                 return Err(());
+///                             }
+///                         }
+///                     }
+///
+///                     Ok(())
+///                 }
+///             })
+///             .map_err(|err| eprintln!("Service Error: {:?}", err))
+///         })?
+///         .run()
+///         .await
+/// }
+/// ```
+#[must_use = "Server does nothing unless you `.await` or poll it"]
+pub struct Server {
+    handle: ServerHandle,
+    fut: BoxFuture<'static, io::Result<()>>,
+}
+
+impl Server {
+    /// Create server build.
+    pub fn build() -> ServerBuilder {
+        ServerBuilder::default()
+    }
+
+    pub(crate) fn new(builder: ServerBuilder) -> Self {
+        Server {
+            handle: ServerHandle::new(builder.cmd_tx.clone()),
+            fut: Box::pin(ServerInner::run(builder)),
+        }
+    }
+
+    /// Get a `Server` handle that can be used issue commands and change it's state.
+    ///
+    /// See [ServerHandle](ServerHandle) for usage.
+    pub fn handle(&self) -> ServerHandle {
+        self.handle.clone()
+    }
+}
+
+impl Future for Server {
+    type Output = io::Result<()>;
+
+    #[inline]
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        Pin::new(&mut Pin::into_inner(self).fut).poll(cx)
+    }
+}
+
+pub struct ServerInner {
+    worker_handles: Vec<WorkerHandleServer>,
+    accept_handle: Option<thread::JoinHandle<()>>,
+    worker_config: ServerWorkerConfig,
+    services: Vec<Box<dyn InternalServiceFactory>>,
+    waker_queue: WakerQueue,
+    system_stop: bool,
+    stopping: bool,
+}
+
+impl ServerInner {
+    async fn run(builder: ServerBuilder) -> io::Result<()> {
+        let (mut this, mut mux) = Self::run_sync(builder)?;
+
+        while let Some(cmd) = mux.next().await {
+            this.handle_cmd(cmd).await;
+
+            if this.stopping {
+                break;
+            }
+        }
+
+        Ok(())
+    }
+
+    fn run_sync(mut builder: ServerBuilder) -> io::Result<(Self, ServerEventMultiplexer)> {
+        // Give log information on what runtime will be used.
+        let is_actix = actix_rt::System::try_current().is_some();
+        let is_tokio = tokio::runtime::Handle::try_current().is_ok();
+
+        match (is_actix, is_tokio) {
+            (true, _) => info!("Actix runtime found; starting in Actix runtime"),
+            (_, true) => info!("Tokio runtime found; starting in existing Tokio runtime"),
+            (_, false) => panic!("Actix or Tokio runtime not found; halting"),
+        }
+
+        for (_, name, lst) in &builder.sockets {
+            info!(
+                r#"starting service: "{}", workers: {}, listening on: {}"#,
+                name,
+                builder.threads,
+                lst.local_addr()
+            );
+        }
+
+        let sockets = mem::take(&mut builder.sockets)
+            .into_iter()
+            .map(|t| (t.0, t.2))
+            .collect();
+
+        let (waker_queue, worker_handles, accept_handle) = Accept::start(sockets, &builder)?;
+
+        let mux = ServerEventMultiplexer {
+            signal_fut: (builder.listen_os_signals).then(Signals::new),
+            cmd_rx: builder.cmd_rx,
+        };
+
+        let server = ServerInner {
+            waker_queue,
+            accept_handle: Some(accept_handle),
+            worker_handles,
+            worker_config: builder.worker_config,
+            services: builder.factories,
+            system_stop: builder.exit,
+            stopping: false,
+        };
+
+        Ok((server, mux))
+    }
+
+    async fn handle_cmd(&mut self, item: ServerCommand) {
+        match item {
+            ServerCommand::Pause(tx) => {
+                self.waker_queue.wake(WakerInterest::Pause);
+                let _ = tx.send(());
+            }
+
+            ServerCommand::Resume(tx) => {
+                self.waker_queue.wake(WakerInterest::Resume);
+                let _ = tx.send(());
+            }
+
+            ServerCommand::Stop {
+                graceful,
+                completion,
+                force_system_stop,
+            } => {
+                self.stopping = true;
+
+                // Signal accept thread to stop.
+                // Signal is non-blocking; we wait for thread to stop later.
+                self.waker_queue.wake(WakerInterest::Stop);
+
+                // send stop signal to workers
+                let workers_stop = self
+                    .worker_handles
+                    .iter()
+                    .map(|worker| worker.stop(graceful))
+                    .collect::<Vec<_>>();
+
+                if graceful {
+                    // wait for all workers to shut down
+                    let _ = join_all(workers_stop).await;
+                }
+
+                // wait for accept thread stop
+                self.accept_handle
+                    .take()
+                    .unwrap()
+                    .join()
+                    .expect("Accept thread must not panic in any case");
+
+                if let Some(tx) = completion {
+                    let _ = tx.send(());
+                }
+
+                if self.system_stop || force_system_stop {
+                    sleep(Duration::from_millis(300)).await;
+                    System::try_current().as_ref().map(System::stop);
+                }
+            }
+
+            ServerCommand::WorkerFaulted(idx) => {
+                // TODO: maybe just return with warning log if not found ?
+                assert!(self.worker_handles.iter().any(|wrk| wrk.idx == idx));
+
+                error!("worker {} has died; restarting", idx);
+
+                let factories = self
+                    .services
+                    .iter()
+                    .map(|service| service.clone_factory())
+                    .collect();
+
+                match ServerWorker::start(
+                    idx,
+                    factories,
+                    self.waker_queue.clone(),
+                    self.worker_config,
+                ) {
+                    Ok((handle_accept, handle_server)) => {
+                        *self
+                            .worker_handles
+                            .iter_mut()
+                            .find(|wrk| wrk.idx == idx)
+                            .unwrap() = handle_server;
+
+                        self.waker_queue.wake(WakerInterest::Worker(handle_accept));
+                    }
+
+                    Err(err) => error!("can not restart worker {}: {}", idx, err),
+                };
+            }
+        }
+    }
+
+    fn map_signal(signal: SignalKind) -> ServerCommand {
+        match signal {
+            SignalKind::Int => {
+                info!("SIGINT received; starting forced shutdown");
+                ServerCommand::Stop {
+                    graceful: false,
+                    completion: None,
+                    force_system_stop: true,
+                }
+            }
+
+            SignalKind::Term => {
+                info!("SIGTERM received; starting graceful shutdown");
+                ServerCommand::Stop {
+                    graceful: true,
+                    completion: None,
+                    force_system_stop: true,
+                }
+            }
+
+            SignalKind::Quit => {
+                info!("SIGQUIT received; starting forced shutdown");
+                ServerCommand::Stop {
+                    graceful: false,
+                    completion: None,
+                    force_system_stop: true,
+                }
+            }
+        }
+    }
+}
+
+struct ServerEventMultiplexer {
+    cmd_rx: UnboundedReceiver<ServerCommand>,
+    signal_fut: Option<Signals>,
+}
+
+impl Stream for ServerEventMultiplexer {
+    type Item = ServerCommand;
+
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+        let this = Pin::into_inner(self);
+
+        if let Some(signal_fut) = &mut this.signal_fut {
+            if let Poll::Ready(signal) = Pin::new(signal_fut).poll(cx) {
+                this.signal_fut = None;
+                return Poll::Ready(Some(ServerInner::map_signal(signal)));
+            }
+        }
+
+        this.cmd_rx.poll_recv(cx)
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/service.rs.html b/src/actix_server/service.rs.html new file mode 100644 index 00000000..f7e05d61 --- /dev/null +++ b/src/actix_server/service.rs.html @@ -0,0 +1,325 @@ +service.rs - source

actix_server/
service.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
use std::{
+    marker::PhantomData,
+    net::SocketAddr,
+    task::{Context, Poll},
+};
+
+use actix_service::{Service, ServiceFactory as BaseServiceFactory};
+use actix_utils::future::{ready, Ready};
+use futures_core::future::LocalBoxFuture;
+use tracing::error;
+
+use crate::{
+    socket::{FromStream, MioStream},
+    worker::WorkerCounterGuard,
+};
+
+#[doc(hidden)]
+pub trait ServerServiceFactory<Stream: FromStream>: Send + Clone + 'static {
+    type Factory: BaseServiceFactory<Stream, Config = ()>;
+
+    fn create(&self) -> Self::Factory;
+}
+
+pub(crate) trait InternalServiceFactory: Send {
+    fn name(&self, token: usize) -> &str;
+
+    fn clone_factory(&self) -> Box<dyn InternalServiceFactory>;
+
+    fn create(&self) -> LocalBoxFuture<'static, Result<(usize, BoxedServerService), ()>>;
+}
+
+pub(crate) type BoxedServerService = Box<
+    dyn Service<
+        (WorkerCounterGuard, MioStream),
+        Response = (),
+        Error = (),
+        Future = Ready<Result<(), ()>>,
+    >,
+>;
+
+pub(crate) struct StreamService<S, I> {
+    service: S,
+    _phantom: PhantomData<I>,
+}
+
+impl<S, I> StreamService<S, I> {
+    pub(crate) fn new(service: S) -> Self {
+        StreamService {
+            service,
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<S, I> Service<(WorkerCounterGuard, MioStream)> for StreamService<S, I>
+where
+    S: Service<I>,
+    S::Future: 'static,
+    S::Error: 'static,
+    I: FromStream,
+{
+    type Response = ();
+    type Error = ();
+    type Future = Ready<Result<(), ()>>;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        self.service.poll_ready(ctx).map_err(|_| ())
+    }
+
+    fn call(&self, (guard, req): (WorkerCounterGuard, MioStream)) -> Self::Future {
+        ready(match FromStream::from_mio(req) {
+            Ok(stream) => {
+                let f = self.service.call(stream);
+                actix_rt::spawn(async move {
+                    let _ = f.await;
+                    drop(guard);
+                });
+                Ok(())
+            }
+            Err(err) => {
+                error!("can not convert to an async TCP stream: {err}");
+                Err(())
+            }
+        })
+    }
+}
+
+pub(crate) struct StreamNewService<F: ServerServiceFactory<Io>, Io: FromStream> {
+    name: String,
+    inner: F,
+    token: usize,
+    addr: SocketAddr,
+    _t: PhantomData<Io>,
+}
+
+impl<F, Io> StreamNewService<F, Io>
+where
+    F: ServerServiceFactory<Io>,
+    Io: FromStream + Send + 'static,
+{
+    pub(crate) fn create(
+        name: String,
+        token: usize,
+        inner: F,
+        addr: SocketAddr,
+    ) -> Box<dyn InternalServiceFactory> {
+        Box::new(Self {
+            name,
+            token,
+            inner,
+            addr,
+            _t: PhantomData,
+        })
+    }
+}
+
+impl<F, Io> InternalServiceFactory for StreamNewService<F, Io>
+where
+    F: ServerServiceFactory<Io>,
+    Io: FromStream + Send + 'static,
+{
+    fn name(&self, _: usize) -> &str {
+        &self.name
+    }
+
+    fn clone_factory(&self) -> Box<dyn InternalServiceFactory> {
+        Box::new(Self {
+            name: self.name.clone(),
+            inner: self.inner.clone(),
+            token: self.token,
+            addr: self.addr,
+            _t: PhantomData,
+        })
+    }
+
+    fn create(&self) -> LocalBoxFuture<'static, Result<(usize, BoxedServerService), ()>> {
+        let token = self.token;
+        let fut = self.inner.create().new_service(());
+        Box::pin(async move {
+            match fut.await {
+                Ok(inner) => {
+                    let service = Box::new(StreamService::new(inner)) as _;
+                    Ok((token, service))
+                }
+                Err(_) => Err(()),
+            }
+        })
+    }
+}
+
+impl<F, T, I> ServerServiceFactory<I> for F
+where
+    F: Fn() -> T + Send + Clone + 'static,
+    T: BaseServiceFactory<I, Config = ()>,
+    I: FromStream,
+{
+    type Factory = T;
+
+    fn create(&self) -> T {
+        (self)()
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/signals.rs.html b/src/actix_server/signals.rs.html new file mode 100644 index 00000000..b8d7efdc --- /dev/null +++ b/src/actix_server/signals.rs.html @@ -0,0 +1,217 @@ +signals.rs - source

actix_server/
signals.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
use std::{
+    fmt,
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use tracing::trace;
+
+/// Types of process signals.
+// #[allow(dead_code)]
+#[derive(Debug, Clone, Copy, PartialEq)]
+#[allow(dead_code)] // variants are never constructed on non-unix
+pub(crate) enum SignalKind {
+    /// `SIGINT`
+    Int,
+
+    /// `SIGTERM`
+    Term,
+
+    /// `SIGQUIT`
+    Quit,
+}
+
+impl fmt::Display for SignalKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match self {
+            SignalKind::Int => "SIGINT",
+            SignalKind::Term => "SIGTERM",
+            SignalKind::Quit => "SIGQUIT",
+        })
+    }
+}
+
+/// Process signal listener.
+pub(crate) struct Signals {
+    #[cfg(not(unix))]
+    signals: futures_core::future::BoxFuture<'static, std::io::Result<()>>,
+
+    #[cfg(unix)]
+    signals: Vec<(SignalKind, actix_rt::signal::unix::Signal)>,
+}
+
+impl Signals {
+    /// Constructs an OS signal listening future.
+    pub(crate) fn new() -> Self {
+        trace!("setting up OS signal listener");
+
+        #[cfg(not(unix))]
+        {
+            Signals {
+                signals: Box::pin(actix_rt::signal::ctrl_c()),
+            }
+        }
+
+        #[cfg(unix)]
+        {
+            use actix_rt::signal::unix;
+
+            let sig_map = [
+                (unix::SignalKind::interrupt(), SignalKind::Int),
+                (unix::SignalKind::terminate(), SignalKind::Term),
+                (unix::SignalKind::quit(), SignalKind::Quit),
+            ];
+
+            let signals = sig_map
+                .iter()
+                .filter_map(|(kind, sig)| {
+                    unix::signal(*kind)
+                        .map(|tokio_sig| (*sig, tokio_sig))
+                        .map_err(|e| {
+                            tracing::error!(
+                                "can not initialize stream handler for {:?} err: {}",
+                                sig,
+                                e
+                            )
+                        })
+                        .ok()
+                })
+                .collect::<Vec<_>>();
+
+            Signals { signals }
+        }
+    }
+}
+
+impl Future for Signals {
+    type Output = SignalKind;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        #[cfg(not(unix))]
+        {
+            self.signals.as_mut().poll(cx).map(|_| SignalKind::Int)
+        }
+
+        #[cfg(unix)]
+        {
+            for (sig, fut) in self.signals.iter_mut() {
+                if fut.poll_recv(cx).is_ready() {
+                    trace!("{} received", sig);
+                    return Poll::Ready(*sig);
+                }
+            }
+
+            Poll::Pending
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/socket.rs.html b/src/actix_server/socket.rs.html new file mode 100644 index 00000000..7444f591 --- /dev/null +++ b/src/actix_server/socket.rs.html @@ -0,0 +1,587 @@ +socket.rs - source

actix_server/
socket.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
pub(crate) use std::net::{
+    SocketAddr as StdSocketAddr, TcpListener as StdTcpListener, ToSocketAddrs,
+};
+use std::{fmt, io};
+
+use actix_rt::net::TcpStream;
+pub(crate) use mio::net::TcpListener as MioTcpListener;
+use mio::{event::Source, Interest, Registry, Token};
+#[cfg(unix)]
+pub(crate) use {
+    mio::net::UnixListener as MioUnixListener, std::os::unix::net::UnixListener as StdUnixListener,
+};
+
+use crate::builder::MpTcp;
+
+pub(crate) enum MioListener {
+    Tcp(MioTcpListener),
+    #[cfg(unix)]
+    Uds(MioUnixListener),
+}
+
+impl MioListener {
+    pub(crate) fn local_addr(&self) -> SocketAddr {
+        match *self {
+            MioListener::Tcp(ref lst) => lst
+                .local_addr()
+                .map(SocketAddr::Tcp)
+                .unwrap_or(SocketAddr::Unknown),
+            #[cfg(unix)]
+            MioListener::Uds(ref lst) => lst
+                .local_addr()
+                .map(SocketAddr::Uds)
+                .unwrap_or(SocketAddr::Unknown),
+        }
+    }
+
+    pub(crate) fn accept(&self) -> io::Result<MioStream> {
+        match *self {
+            MioListener::Tcp(ref lst) => lst.accept().map(|(stream, _)| MioStream::Tcp(stream)),
+            #[cfg(unix)]
+            MioListener::Uds(ref lst) => lst.accept().map(|(stream, _)| MioStream::Uds(stream)),
+        }
+    }
+}
+
+impl Source for MioListener {
+    fn register(
+        &mut self,
+        registry: &Registry,
+        token: Token,
+        interests: Interest,
+    ) -> io::Result<()> {
+        match *self {
+            MioListener::Tcp(ref mut lst) => lst.register(registry, token, interests),
+            #[cfg(unix)]
+            MioListener::Uds(ref mut lst) => lst.register(registry, token, interests),
+        }
+    }
+
+    fn reregister(
+        &mut self,
+        registry: &Registry,
+        token: Token,
+        interests: Interest,
+    ) -> io::Result<()> {
+        match *self {
+            MioListener::Tcp(ref mut lst) => lst.reregister(registry, token, interests),
+            #[cfg(unix)]
+            MioListener::Uds(ref mut lst) => lst.reregister(registry, token, interests),
+        }
+    }
+
+    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
+        match *self {
+            MioListener::Tcp(ref mut lst) => lst.deregister(registry),
+            #[cfg(unix)]
+            MioListener::Uds(ref mut lst) => {
+                let res = lst.deregister(registry);
+
+                // cleanup file path
+                if let Ok(addr) = lst.local_addr() {
+                    if let Some(path) = addr.as_pathname() {
+                        let _ = std::fs::remove_file(path);
+                    }
+                }
+                res
+            }
+        }
+    }
+}
+
+impl From<StdTcpListener> for MioListener {
+    fn from(lst: StdTcpListener) -> Self {
+        MioListener::Tcp(MioTcpListener::from_std(lst))
+    }
+}
+
+#[cfg(unix)]
+impl From<StdUnixListener> for MioListener {
+    fn from(lst: StdUnixListener) -> Self {
+        MioListener::Uds(MioUnixListener::from_std(lst))
+    }
+}
+
+impl fmt::Debug for MioListener {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            MioListener::Tcp(ref lst) => write!(f, "{:?}", lst),
+            #[cfg(unix)]
+            MioListener::Uds(ref lst) => write!(f, "{:?}", lst),
+        }
+    }
+}
+
+impl fmt::Display for MioListener {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            MioListener::Tcp(ref lst) => write!(f, "{:?}", lst),
+            #[cfg(unix)]
+            MioListener::Uds(ref lst) => write!(f, "{:?}", lst),
+        }
+    }
+}
+
+pub(crate) enum SocketAddr {
+    Unknown,
+    Tcp(StdSocketAddr),
+    #[cfg(unix)]
+    Uds(std::os::unix::net::SocketAddr),
+}
+
+impl fmt::Display for SocketAddr {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            Self::Unknown => write!(f, "Unknown SocketAddr"),
+            Self::Tcp(ref addr) => write!(f, "{}", addr),
+            #[cfg(unix)]
+            Self::Uds(ref addr) => write!(f, "{:?}", addr),
+        }
+    }
+}
+
+impl fmt::Debug for SocketAddr {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            Self::Unknown => write!(f, "Unknown SocketAddr"),
+            Self::Tcp(ref addr) => write!(f, "{:?}", addr),
+            #[cfg(unix)]
+            Self::Uds(ref addr) => write!(f, "{:?}", addr),
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum MioStream {
+    Tcp(mio::net::TcpStream),
+    #[cfg(unix)]
+    Uds(mio::net::UnixStream),
+}
+
+/// Helper trait for converting a Mio stream into a Tokio stream.
+pub trait FromStream: Sized {
+    fn from_mio(sock: MioStream) -> io::Result<Self>;
+}
+
+#[cfg(windows)]
+mod win_impl {
+    use std::os::windows::io::{FromRawSocket, IntoRawSocket};
+
+    use super::*;
+
+    // TODO: This is a workaround and we need an efficient way to convert between Mio and Tokio stream
+    impl FromStream for TcpStream {
+        fn from_mio(sock: MioStream) -> io::Result<Self> {
+            match sock {
+                MioStream::Tcp(mio) => {
+                    let raw = IntoRawSocket::into_raw_socket(mio);
+                    // SAFETY: This is an in-place conversion from Mio stream to Tokio stream.
+                    TcpStream::from_std(unsafe { FromRawSocket::from_raw_socket(raw) })
+                }
+            }
+        }
+    }
+}
+
+#[cfg(unix)]
+mod unix_impl {
+    use std::os::unix::io::{FromRawFd, IntoRawFd};
+
+    use actix_rt::net::UnixStream;
+
+    use super::*;
+
+    // HACK: This is a workaround and we need an efficient way to convert between Mio and Tokio stream
+    impl FromStream for TcpStream {
+        fn from_mio(sock: MioStream) -> io::Result<Self> {
+            match sock {
+                MioStream::Tcp(mio) => {
+                    let raw = IntoRawFd::into_raw_fd(mio);
+                    // SAFETY: This is an in-place conversion from Mio stream to Tokio stream.
+                    TcpStream::from_std(unsafe { FromRawFd::from_raw_fd(raw) })
+                }
+                MioStream::Uds(_) => {
+                    panic!("Should not happen, bug in server impl");
+                }
+            }
+        }
+    }
+
+    // HACK: This is a workaround and we need an efficient way to convert between Mio and Tokio stream
+    impl FromStream for UnixStream {
+        fn from_mio(sock: MioStream) -> io::Result<Self> {
+            match sock {
+                MioStream::Tcp(_) => panic!("Should not happen, bug in server impl"),
+                MioStream::Uds(mio) => {
+                    let raw = IntoRawFd::into_raw_fd(mio);
+                    // SAFETY: This is an in-place conversion from Mio stream to Tokio stream.
+                    UnixStream::from_std(unsafe { FromRawFd::from_raw_fd(raw) })
+                }
+            }
+        }
+    }
+}
+
+pub(crate) fn create_mio_tcp_listener(
+    addr: StdSocketAddr,
+    backlog: u32,
+    mptcp: &MpTcp,
+) -> io::Result<MioTcpListener> {
+    use socket2::{Domain, Protocol, Socket, Type};
+
+    #[cfg(not(target_os = "linux"))]
+    let protocol = Protocol::TCP;
+    #[cfg(target_os = "linux")]
+    let protocol = if matches!(mptcp, MpTcp::Disabled) {
+        Protocol::TCP
+    } else {
+        Protocol::MPTCP
+    };
+
+    let socket = match Socket::new(Domain::for_address(addr), Type::STREAM, Some(protocol)) {
+        Ok(sock) => sock,
+
+        Err(err) if matches!(mptcp, MpTcp::TcpFallback) => {
+            tracing::warn!("binding socket as MPTCP failed: {err}");
+            tracing::warn!("falling back to TCP");
+            Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP))?
+        }
+
+        Err(err) => return Err(err),
+    };
+
+    socket.set_reuse_address(true)?;
+    socket.set_nonblocking(true)?;
+    socket.bind(&addr.into())?;
+    socket.listen(backlog as i32)?;
+
+    Ok(MioTcpListener::from_std(StdTcpListener::from(socket)))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn socket_addr() {
+        let addr = SocketAddr::Tcp("127.0.0.1:8080".parse().unwrap());
+        assert!(format!("{:?}", addr).contains("127.0.0.1:8080"));
+        assert_eq!(format!("{}", addr), "127.0.0.1:8080");
+
+        let addr: StdSocketAddr = "127.0.0.1:0".parse().unwrap();
+        let lst = create_mio_tcp_listener(addr, 128, &MpTcp::Disabled).unwrap();
+        let lst = MioListener::Tcp(lst);
+        assert!(format!("{:?}", lst).contains("TcpListener"));
+        assert!(format!("{}", lst).contains("127.0.0.1"));
+    }
+
+    #[test]
+    #[cfg(unix)]
+    fn uds() {
+        let _ = std::fs::remove_file("/tmp/sock.xxxxx");
+        if let Ok(socket) = MioUnixListener::bind("/tmp/sock.xxxxx") {
+            let addr = socket.local_addr().expect("Couldn't get local address");
+            let a = SocketAddr::Uds(addr);
+            assert!(format!("{:?}", a).contains("/tmp/sock.xxxxx"));
+            assert!(format!("{}", a).contains("/tmp/sock.xxxxx"));
+
+            let lst = MioListener::Uds(socket);
+            assert!(format!("{:?}", lst).contains("/tmp/sock.xxxxx"));
+            assert!(format!("{}", lst).contains("/tmp/sock.xxxxx"));
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/test_server.rs.html b/src/actix_server/test_server.rs.html new file mode 100644 index 00000000..51547e6b --- /dev/null +++ b/src/actix_server/test_server.rs.html @@ -0,0 +1,307 @@ +test_server.rs - source

actix_server/
test_server.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
use std::{io, net, sync::mpsc, thread};
+
+use actix_rt::{net::TcpStream, System};
+
+use crate::{Server, ServerBuilder, ServerHandle, ServerServiceFactory};
+
+/// A testing server.
+///
+/// `TestServer` is very simple test server that simplify process of writing integration tests for
+/// network applications.
+///
+/// # Examples
+/// ```
+/// use actix_service::fn_service;
+/// use actix_server::TestServer;
+///
+/// #[actix_rt::main]
+/// async fn main() {
+///     let srv = TestServer::start(|| fn_service(
+///         |sock| async move {
+///             println!("New connection: {:?}", sock);
+///             Ok::<_, ()>(())
+///         }
+///     ));
+///
+///     println!("SOCKET: {:?}", srv.connect());
+/// }
+/// ```
+pub struct TestServer;
+
+/// Test server handle.
+pub struct TestServerHandle {
+    addr: net::SocketAddr,
+    host: String,
+    port: u16,
+    server_handle: ServerHandle,
+    thread_handle: Option<thread::JoinHandle<io::Result<()>>>,
+}
+
+impl TestServer {
+    /// Start new `TestServer` using application factory and default server config.
+    pub fn start(factory: impl ServerServiceFactory<TcpStream>) -> TestServerHandle {
+        Self::start_with_builder(Server::build(), factory)
+    }
+
+    /// Start new `TestServer` using application factory and server builder.
+    pub fn start_with_builder(
+        server_builder: ServerBuilder,
+        factory: impl ServerServiceFactory<TcpStream>,
+    ) -> TestServerHandle {
+        let (tx, rx) = mpsc::channel();
+
+        // run server in separate thread
+        let thread_handle = thread::spawn(move || {
+            let lst = net::TcpListener::bind("127.0.0.1:0").unwrap();
+            let local_addr = lst.local_addr().unwrap();
+
+            System::new().block_on(async {
+                let server = server_builder
+                    .listen("test", lst, factory)
+                    .unwrap()
+                    .workers(1)
+                    .disable_signals()
+                    .run();
+
+                tx.send((server.handle(), local_addr)).unwrap();
+                server.await
+            })
+        });
+
+        let (server_handle, addr) = rx.recv().unwrap();
+
+        let host = format!("{}", addr.ip());
+        let port = addr.port();
+
+        TestServerHandle {
+            addr,
+            host,
+            port,
+            server_handle,
+            thread_handle: Some(thread_handle),
+        }
+    }
+
+    /// Get first available unused local address.
+    pub fn unused_addr() -> net::SocketAddr {
+        use socket2::{Domain, Protocol, Socket, Type};
+
+        let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
+        let domain = Domain::for_address(addr);
+        let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP)).unwrap();
+
+        socket.set_reuse_address(true).unwrap();
+        socket.set_nonblocking(true).unwrap();
+        socket.bind(&addr.into()).unwrap();
+        socket.listen(1024).unwrap();
+
+        net::TcpListener::from(socket).local_addr().unwrap()
+    }
+}
+
+impl TestServerHandle {
+    /// Test server host.
+    pub fn host(&self) -> &str {
+        &self.host
+    }
+
+    /// Test server port.
+    pub fn port(&self) -> u16 {
+        self.port
+    }
+
+    /// Get test server address.
+    pub fn addr(&self) -> net::SocketAddr {
+        self.addr
+    }
+
+    /// Stop server.
+    fn stop(&mut self) {
+        drop(self.server_handle.stop(false));
+        self.thread_handle.take().unwrap().join().unwrap().unwrap();
+    }
+
+    /// Connect to server, returning a Tokio `TcpStream`.
+    pub fn connect(&self) -> io::Result<TcpStream> {
+        TcpStream::from_std(net::TcpStream::connect(self.addr)?)
+    }
+}
+
+impl Drop for TestServerHandle {
+    fn drop(&mut self) {
+        self.stop()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use actix_service::fn_service;
+
+    use super::*;
+
+    #[tokio::test]
+    async fn connect_in_tokio_runtime() {
+        let srv = TestServer::start(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
+        assert!(srv.connect().is_ok());
+    }
+
+    #[actix_rt::test]
+    async fn connect_in_actix_runtime() {
+        let srv = TestServer::start(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
+        assert!(srv.connect().is_ok());
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_server/waker_queue.rs.html b/src/actix_server/waker_queue.rs.html new file mode 100644 index 00000000..1ff7dce7 --- /dev/null +++ b/src/actix_server/waker_queue.rs.html @@ -0,0 +1,169 @@ +waker_queue.rs - source

actix_server/
waker_queue.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
use std::{
+    collections::VecDeque,
+    ops::Deref,
+    sync::{Arc, Mutex, MutexGuard},
+};
+
+use mio::{Registry, Token as MioToken, Waker};
+
+use crate::worker::WorkerHandleAccept;
+
+/// Waker token for `mio::Poll` instance.
+pub(crate) const WAKER_TOKEN: MioToken = MioToken(usize::MAX);
+
+/// `mio::Waker` with a queue for waking up the `Accept`'s `Poll` and contains the `WakerInterest`
+/// the `Poll` would want to look into.
+pub(crate) struct WakerQueue(Arc<(Waker, Mutex<VecDeque<WakerInterest>>)>);
+
+impl Clone for WakerQueue {
+    fn clone(&self) -> Self {
+        Self(self.0.clone())
+    }
+}
+
+impl Deref for WakerQueue {
+    type Target = (Waker, Mutex<VecDeque<WakerInterest>>);
+
+    fn deref(&self) -> &Self::Target {
+        self.0.deref()
+    }
+}
+
+impl WakerQueue {
+    /// Construct a waker queue with given `Poll`'s `Registry` and capacity.
+    ///
+    /// A fixed `WAKER_TOKEN` is used to identify the wake interest and the `Poll` needs to match
+    /// event's token for it to properly handle `WakerInterest`.
+    pub(crate) fn new(registry: &Registry) -> std::io::Result<Self> {
+        let waker = Waker::new(registry, WAKER_TOKEN)?;
+        let queue = Mutex::new(VecDeque::with_capacity(16));
+
+        Ok(Self(Arc::new((waker, queue))))
+    }
+
+    /// Push a new interest to the queue and wake up the accept poll afterwards.
+    pub(crate) fn wake(&self, interest: WakerInterest) {
+        let (waker, queue) = self.deref();
+
+        queue
+            .lock()
+            .expect("Failed to lock WakerQueue")
+            .push_back(interest);
+
+        waker
+            .wake()
+            .unwrap_or_else(|e| panic!("can not wake up Accept Poll: {}", e));
+    }
+
+    /// Get a MutexGuard of the waker queue.
+    pub(crate) fn guard(&self) -> MutexGuard<'_, VecDeque<WakerInterest>> {
+        self.deref().1.lock().expect("Failed to lock WakerQueue")
+    }
+
+    /// Reset the waker queue so it does not grow infinitely.
+    pub(crate) fn reset(queue: &mut VecDeque<WakerInterest>) {
+        std::mem::swap(&mut VecDeque::<WakerInterest>::with_capacity(16), queue);
+    }
+}
+
+/// Types of interests we would look into when `Accept`'s `Poll` is waked up by waker.
+///
+/// These interests should not be confused with `mio::Interest` and mostly not I/O related
+pub(crate) enum WakerInterest {
+    /// `WorkerAvailable` is an interest from `Worker` notifying `Accept` there is a worker
+    /// available and can accept new tasks.
+    WorkerAvailable(usize),
+    /// `Pause`, `Resume`, `Stop` Interest are from `ServerBuilder` future. It listens to
+    /// `ServerCommand` and notify `Accept` to do exactly these tasks.
+    Pause,
+    Resume,
+    Stop,
+    /// `Worker` is an interest that is triggered after a worker faults. This is determined by
+    /// trying to send work to it. `Accept` would be waked up and add the new `WorkerHandleAccept`.
+    Worker(WorkerHandleAccept),
+}
+
\ No newline at end of file diff --git a/src/actix_server/worker.rs.html b/src/actix_server/worker.rs.html new file mode 100644 index 00000000..f828a732 --- /dev/null +++ b/src/actix_server/worker.rs.html @@ -0,0 +1,1463 @@ +worker.rs - source

actix_server/
worker.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
use std::{
+    future::Future,
+    io, mem,
+    num::NonZeroUsize,
+    pin::Pin,
+    rc::Rc,
+    sync::{
+        atomic::{AtomicUsize, Ordering},
+        Arc,
+    },
+    task::{Context, Poll},
+    time::Duration,
+};
+
+use actix_rt::{
+    spawn,
+    time::{sleep, Instant, Sleep},
+    Arbiter, ArbiterHandle, System,
+};
+use futures_core::{future::LocalBoxFuture, ready};
+use tokio::sync::{
+    mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
+    oneshot,
+};
+use tracing::{error, info, trace};
+
+use crate::{
+    service::{BoxedServerService, InternalServiceFactory},
+    socket::MioStream,
+    waker_queue::{WakerInterest, WakerQueue},
+};
+
+/// Stop worker message. Returns `true` on successful graceful shutdown
+/// and `false` if some connections still alive when shutdown execute.
+pub(crate) struct Stop {
+    graceful: bool,
+    tx: oneshot::Sender<bool>,
+}
+
+#[derive(Debug)]
+pub(crate) struct Conn {
+    pub io: MioStream,
+    pub token: usize,
+}
+
+/// Create accept and server worker handles.
+fn handle_pair(
+    idx: usize,
+    conn_tx: UnboundedSender<Conn>,
+    stop_tx: UnboundedSender<Stop>,
+    counter: Counter,
+) -> (WorkerHandleAccept, WorkerHandleServer) {
+    let accept = WorkerHandleAccept {
+        idx,
+        conn_tx,
+        counter,
+    };
+
+    let server = WorkerHandleServer { idx, stop_tx };
+
+    (accept, server)
+}
+
+/// counter: Arc<AtomicUsize> field is owned by `Accept` thread and `ServerWorker` thread.
+///
+/// `Accept` would increment the counter and `ServerWorker` would decrement it.
+///
+/// # Atomic Ordering:
+///
+/// `Accept` always look into it's cached `Availability` field for `ServerWorker` state.
+/// It lazily increment counter after successful dispatching new work to `ServerWorker`.
+/// On reaching counter limit `Accept` update it's cached `Availability` and mark worker as
+/// unable to accept any work.
+///
+/// `ServerWorker` always decrement the counter when every work received from `Accept` is done.
+/// On reaching counter limit worker would use `mio::Waker` and `WakerQueue` to wake up `Accept`
+/// and notify it to update cached `Availability` again to mark worker as able to accept work again.
+///
+/// Hence, a wake up would only happen after `Accept` increment it to limit.
+/// And a decrement to limit always wake up `Accept`.
+#[derive(Clone)]
+pub(crate) struct Counter {
+    counter: Arc<AtomicUsize>,
+    limit: usize,
+}
+
+impl Counter {
+    pub(crate) fn new(limit: usize) -> Self {
+        Self {
+            counter: Arc::new(AtomicUsize::new(1)),
+            limit,
+        }
+    }
+
+    /// Increment counter by 1 and return true when hitting limit
+    #[inline(always)]
+    pub(crate) fn inc(&self) -> bool {
+        self.counter.fetch_add(1, Ordering::Relaxed) != self.limit
+    }
+
+    /// Decrement counter by 1 and return true if crossing limit.
+    #[inline(always)]
+    pub(crate) fn dec(&self) -> bool {
+        self.counter.fetch_sub(1, Ordering::Relaxed) == self.limit
+    }
+
+    pub(crate) fn total(&self) -> usize {
+        self.counter.load(Ordering::SeqCst) - 1
+    }
+}
+
+pub(crate) struct WorkerCounter {
+    idx: usize,
+    inner: Rc<(WakerQueue, Counter)>,
+}
+
+impl Clone for WorkerCounter {
+    fn clone(&self) -> Self {
+        Self {
+            idx: self.idx,
+            inner: self.inner.clone(),
+        }
+    }
+}
+
+impl WorkerCounter {
+    pub(crate) fn new(idx: usize, waker_queue: WakerQueue, counter: Counter) -> Self {
+        Self {
+            idx,
+            inner: Rc::new((waker_queue, counter)),
+        }
+    }
+
+    #[inline(always)]
+    pub(crate) fn guard(&self) -> WorkerCounterGuard {
+        WorkerCounterGuard(self.clone())
+    }
+
+    fn total(&self) -> usize {
+        self.inner.1.total()
+    }
+}
+
+pub(crate) struct WorkerCounterGuard(WorkerCounter);
+
+impl Drop for WorkerCounterGuard {
+    fn drop(&mut self) {
+        let (waker_queue, counter) = &*self.0.inner;
+        if counter.dec() {
+            waker_queue.wake(WakerInterest::WorkerAvailable(self.0.idx));
+        }
+    }
+}
+
+/// Handle to worker that can send connection message to worker and share the availability of worker
+/// to other threads.
+///
+/// Held by [Accept](crate::accept::Accept).
+pub(crate) struct WorkerHandleAccept {
+    idx: usize,
+    conn_tx: UnboundedSender<Conn>,
+    counter: Counter,
+}
+
+impl WorkerHandleAccept {
+    #[inline(always)]
+    pub(crate) fn idx(&self) -> usize {
+        self.idx
+    }
+
+    #[inline(always)]
+    pub(crate) fn send(&self, conn: Conn) -> Result<(), Conn> {
+        self.conn_tx.send(conn).map_err(|msg| msg.0)
+    }
+
+    #[inline(always)]
+    pub(crate) fn inc_counter(&self) -> bool {
+        self.counter.inc()
+    }
+}
+
+/// Handle to worker than can send stop message to worker.
+///
+/// Held by [ServerBuilder](crate::builder::ServerBuilder).
+#[derive(Debug)]
+pub(crate) struct WorkerHandleServer {
+    pub(crate) idx: usize,
+    stop_tx: UnboundedSender<Stop>,
+}
+
+impl WorkerHandleServer {
+    pub(crate) fn stop(&self, graceful: bool) -> oneshot::Receiver<bool> {
+        let (tx, rx) = oneshot::channel();
+        let _ = self.stop_tx.send(Stop { graceful, tx });
+        rx
+    }
+}
+
+/// Service worker.
+///
+/// Worker accepts Socket objects via unbounded channel and starts stream processing.
+pub(crate) struct ServerWorker {
+    // UnboundedReceiver<Conn> should always be the first field.
+    // It must be dropped as soon as ServerWorker dropping.
+    conn_rx: UnboundedReceiver<Conn>,
+    stop_rx: UnboundedReceiver<Stop>,
+    counter: WorkerCounter,
+    services: Box<[WorkerService]>,
+    factories: Box<[Box<dyn InternalServiceFactory>]>,
+    state: WorkerState,
+    shutdown_timeout: Duration,
+}
+
+struct WorkerService {
+    factory_idx: usize,
+    status: WorkerServiceStatus,
+    service: BoxedServerService,
+}
+
+impl WorkerService {
+    fn created(&mut self, service: BoxedServerService) {
+        self.service = service;
+        self.status = WorkerServiceStatus::Unavailable;
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum WorkerServiceStatus {
+    Available,
+    Unavailable,
+    Failed,
+    Restarting,
+    Stopping,
+    Stopped,
+}
+
+impl Default for WorkerServiceStatus {
+    fn default() -> Self {
+        Self::Unavailable
+    }
+}
+
+/// Config for worker behavior passed down from server builder.
+#[derive(Debug, Clone, Copy)]
+pub(crate) struct ServerWorkerConfig {
+    shutdown_timeout: Duration,
+    max_blocking_threads: usize,
+    max_concurrent_connections: usize,
+}
+
+impl Default for ServerWorkerConfig {
+    fn default() -> Self {
+        let parallelism = std::thread::available_parallelism().map_or(2, NonZeroUsize::get);
+
+        // 512 is the default max blocking thread count of a Tokio runtime.
+        let max_blocking_threads = std::cmp::max(512 / parallelism, 1);
+
+        Self {
+            shutdown_timeout: Duration::from_secs(30),
+            max_blocking_threads,
+            max_concurrent_connections: 25600,
+        }
+    }
+}
+
+impl ServerWorkerConfig {
+    pub(crate) fn max_blocking_threads(&mut self, num: usize) {
+        self.max_blocking_threads = num;
+    }
+
+    pub(crate) fn max_concurrent_connections(&mut self, num: usize) {
+        self.max_concurrent_connections = num;
+    }
+
+    pub(crate) fn shutdown_timeout(&mut self, dur: Duration) {
+        self.shutdown_timeout = dur;
+    }
+}
+
+impl ServerWorker {
+    pub(crate) fn start(
+        idx: usize,
+        factories: Vec<Box<dyn InternalServiceFactory>>,
+        waker_queue: WakerQueue,
+        config: ServerWorkerConfig,
+    ) -> io::Result<(WorkerHandleAccept, WorkerHandleServer)> {
+        trace!("starting server worker {}", idx);
+
+        let (tx1, conn_rx) = unbounded_channel();
+        let (tx2, stop_rx) = unbounded_channel();
+
+        let counter = Counter::new(config.max_concurrent_connections);
+        let pair = handle_pair(idx, tx1, tx2, counter.clone());
+
+        // get actix system context if it is set
+        let actix_system = System::try_current();
+
+        // get tokio runtime handle if it is set
+        let tokio_handle = tokio::runtime::Handle::try_current().ok();
+
+        // service factories initialization channel
+        let (factory_tx, factory_rx) = std::sync::mpsc::sync_channel::<io::Result<()>>(1);
+
+        // outline of following code:
+        //
+        // if system exists
+        //   if uring enabled
+        //     start arbiter using uring method
+        //   else
+        //     start arbiter with regular tokio
+        // else
+        //   if uring enabled
+        //     start uring in spawned thread
+        //   else
+        //     start regular tokio in spawned thread
+
+        // every worker runs in it's own thread and tokio runtime.
+        // use a custom tokio runtime builder to change the settings of runtime.
+
+        match (actix_system, tokio_handle) {
+            (None, None) => {
+                panic!("No runtime detected. Start a Tokio (or Actix) runtime.");
+            }
+
+            // no actix system
+            (None, Some(rt_handle)) => {
+                std::thread::Builder::new()
+                    .name(format!("actix-server worker {}", idx))
+                    .spawn(move || {
+                        let (worker_stopped_tx, worker_stopped_rx) = oneshot::channel();
+
+                        // local set for running service init futures and worker services
+                        let ls = tokio::task::LocalSet::new();
+
+                        // init services using existing Tokio runtime (so probably on main thread)
+                        let services = rt_handle.block_on(ls.run_until(async {
+                            let mut services = Vec::new();
+
+                            for (idx, factory) in factories.iter().enumerate() {
+                                match factory.create().await {
+                                    Ok((token, svc)) => services.push((idx, token, svc)),
+
+                                    Err(err) => {
+                                        error!("can not start worker: {:?}", err);
+                                        return Err(io::Error::new(
+                                            io::ErrorKind::Other,
+                                            format!("can not start server service {}", idx),
+                                        ));
+                                    }
+                                }
+                            }
+
+                            Ok(services)
+                        }));
+
+                        let services = match services {
+                            Ok(services) => {
+                                factory_tx.send(Ok(())).unwrap();
+                                services
+                            }
+                            Err(err) => {
+                                factory_tx.send(Err(err)).unwrap();
+                                return;
+                            }
+                        };
+
+                        let worker_services = wrap_worker_services(services);
+
+                        let worker_fut = async move {
+                            // spawn to make sure ServerWorker runs as non boxed future.
+                            spawn(async move {
+                                ServerWorker {
+                                    conn_rx,
+                                    stop_rx,
+                                    services: worker_services.into_boxed_slice(),
+                                    counter: WorkerCounter::new(idx, waker_queue, counter),
+                                    factories: factories.into_boxed_slice(),
+                                    state: WorkerState::default(),
+                                    shutdown_timeout: config.shutdown_timeout,
+                                }
+                                .await;
+
+                                // wake up outermost task waiting for shutdown
+                                worker_stopped_tx.send(()).unwrap();
+                            });
+
+                            worker_stopped_rx.await.unwrap();
+                        };
+
+                        #[cfg(all(target_os = "linux", feature = "io-uring"))]
+                        {
+                            // TODO: pass max blocking thread config when tokio-uring enable configuration
+                            // on building runtime.
+                            let _ = config.max_blocking_threads;
+                            tokio_uring::start(worker_fut);
+                        }
+
+                        #[cfg(not(all(target_os = "linux", feature = "io-uring")))]
+                        {
+                            let rt = tokio::runtime::Builder::new_current_thread()
+                                .enable_all()
+                                .max_blocking_threads(config.max_blocking_threads)
+                                .build()
+                                .unwrap();
+
+                            rt.block_on(ls.run_until(worker_fut));
+                        }
+                    })
+                    .expect("cannot spawn server worker thread");
+            }
+
+            // with actix system
+            (Some(_sys), _) => {
+                #[cfg(all(target_os = "linux", feature = "io-uring"))]
+                let arbiter = {
+                    // TODO: pass max blocking thread config when tokio-uring enable configuration
+                    // on building runtime.
+                    let _ = config.max_blocking_threads;
+                    Arbiter::new()
+                };
+
+                #[cfg(not(all(target_os = "linux", feature = "io-uring")))]
+                let arbiter = {
+                    Arbiter::with_tokio_rt(move || {
+                        tokio::runtime::Builder::new_current_thread()
+                            .enable_all()
+                            .max_blocking_threads(config.max_blocking_threads)
+                            .build()
+                            .unwrap()
+                    })
+                };
+
+                arbiter.spawn(async move {
+                    // spawn_local to run !Send future tasks.
+                    spawn(async move {
+                        let mut services = Vec::new();
+
+                        for (idx, factory) in factories.iter().enumerate() {
+                            match factory.create().await {
+                                Ok((token, svc)) => services.push((idx, token, svc)),
+
+                                Err(err) => {
+                                    error!("can not start worker: {:?}", err);
+                                    Arbiter::current().stop();
+                                    factory_tx
+                                        .send(Err(io::Error::new(
+                                            io::ErrorKind::Other,
+                                            format!("can not start server service {}", idx),
+                                        )))
+                                        .unwrap();
+                                    return;
+                                }
+                            }
+                        }
+
+                        factory_tx.send(Ok(())).unwrap();
+
+                        let worker_services = wrap_worker_services(services);
+
+                        // spawn to make sure ServerWorker runs as non boxed future.
+                        spawn(ServerWorker {
+                            conn_rx,
+                            stop_rx,
+                            services: worker_services.into_boxed_slice(),
+                            counter: WorkerCounter::new(idx, waker_queue, counter),
+                            factories: factories.into_boxed_slice(),
+                            state: Default::default(),
+                            shutdown_timeout: config.shutdown_timeout,
+                        });
+                    });
+                });
+            }
+        };
+
+        // wait for service factories initialization
+        factory_rx.recv().unwrap()?;
+
+        Ok(pair)
+    }
+
+    fn restart_service(&mut self, idx: usize, factory_id: usize) {
+        let factory = &self.factories[factory_id];
+        trace!("service {:?} failed, restarting", factory.name(idx));
+        self.services[idx].status = WorkerServiceStatus::Restarting;
+        self.state = WorkerState::Restarting(Restart {
+            factory_id,
+            token: idx,
+            fut: factory.create(),
+        });
+    }
+
+    fn shutdown(&mut self, force: bool) {
+        self.services
+            .iter_mut()
+            .filter(|srv| srv.status == WorkerServiceStatus::Available)
+            .for_each(|srv| {
+                srv.status = if force {
+                    WorkerServiceStatus::Stopped
+                } else {
+                    WorkerServiceStatus::Stopping
+                };
+            });
+    }
+
+    fn check_readiness(&mut self, cx: &mut Context<'_>) -> Result<bool, (usize, usize)> {
+        let mut ready = true;
+        for (idx, srv) in self.services.iter_mut().enumerate() {
+            if srv.status == WorkerServiceStatus::Available
+                || srv.status == WorkerServiceStatus::Unavailable
+            {
+                match srv.service.poll_ready(cx) {
+                    Poll::Ready(Ok(_)) => {
+                        if srv.status == WorkerServiceStatus::Unavailable {
+                            trace!(
+                                "service {:?} is available",
+                                self.factories[srv.factory_idx].name(idx)
+                            );
+                            srv.status = WorkerServiceStatus::Available;
+                        }
+                    }
+                    Poll::Pending => {
+                        ready = false;
+
+                        if srv.status == WorkerServiceStatus::Available {
+                            trace!(
+                                "service {:?} is unavailable",
+                                self.factories[srv.factory_idx].name(idx)
+                            );
+                            srv.status = WorkerServiceStatus::Unavailable;
+                        }
+                    }
+                    Poll::Ready(Err(_)) => {
+                        error!(
+                            "service {:?} readiness check returned error, restarting",
+                            self.factories[srv.factory_idx].name(idx)
+                        );
+                        srv.status = WorkerServiceStatus::Failed;
+                        return Err((idx, srv.factory_idx));
+                    }
+                }
+            }
+        }
+
+        Ok(ready)
+    }
+}
+
+enum WorkerState {
+    Available,
+    Unavailable,
+    Restarting(Restart),
+    Shutdown(Shutdown),
+}
+
+struct Restart {
+    factory_id: usize,
+    token: usize,
+    fut: LocalBoxFuture<'static, Result<(usize, BoxedServerService), ()>>,
+}
+
+/// State necessary for server shutdown.
+struct Shutdown {
+    // Interval for checking the shutdown progress.
+    timer: Pin<Box<Sleep>>,
+
+    /// Start time of shutdown.
+    start_from: Instant,
+
+    /// Notify caller of the shutdown outcome (graceful/force).
+    tx: oneshot::Sender<bool>,
+}
+
+impl Default for WorkerState {
+    fn default() -> Self {
+        Self::Unavailable
+    }
+}
+
+impl Drop for ServerWorker {
+    fn drop(&mut self) {
+        Arbiter::try_current().as_ref().map(ArbiterHandle::stop);
+    }
+}
+
+impl Future for ServerWorker {
+    type Output = ();
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.as_mut().get_mut();
+
+        // `StopWorker` message handler
+        if let Poll::Ready(Some(Stop { graceful, tx })) = this.stop_rx.poll_recv(cx) {
+            let num = this.counter.total();
+            if num == 0 {
+                info!("shutting down idle worker");
+                let _ = tx.send(true);
+                return Poll::Ready(());
+            } else if graceful {
+                info!("graceful worker shutdown; finishing {} connections", num);
+                this.shutdown(false);
+
+                this.state = WorkerState::Shutdown(Shutdown {
+                    timer: Box::pin(sleep(Duration::from_secs(1))),
+                    start_from: Instant::now(),
+                    tx,
+                });
+            } else {
+                info!("force shutdown worker, closing {} connections", num);
+                this.shutdown(true);
+
+                let _ = tx.send(false);
+                return Poll::Ready(());
+            }
+        }
+
+        match this.state {
+            WorkerState::Unavailable => match this.check_readiness(cx) {
+                Ok(true) => {
+                    this.state = WorkerState::Available;
+                    self.poll(cx)
+                }
+                Ok(false) => Poll::Pending,
+                Err((token, idx)) => {
+                    this.restart_service(token, idx);
+                    self.poll(cx)
+                }
+            },
+
+            WorkerState::Restarting(ref mut restart) => {
+                let factory_id = restart.factory_id;
+                let token = restart.token;
+
+                let (token_new, service) =
+                    ready!(restart.fut.as_mut().poll(cx)).unwrap_or_else(|_| {
+                        panic!(
+                            "Can not restart {:?} service",
+                            this.factories[factory_id].name(token)
+                        )
+                    });
+
+                assert_eq!(token, token_new);
+
+                trace!(
+                    "service {:?} has been restarted",
+                    this.factories[factory_id].name(token)
+                );
+
+                this.services[token].created(service);
+                this.state = WorkerState::Unavailable;
+
+                self.poll(cx)
+            }
+
+            WorkerState::Shutdown(ref mut shutdown) => {
+                // drop all pending connections in rx channel.
+                while let Poll::Ready(Some(conn)) = this.conn_rx.poll_recv(cx) {
+                    // WorkerCounterGuard is needed as Accept thread has incremented counter.
+                    // It's guard's job to decrement the counter together with drop of Conn.
+                    let guard = this.counter.guard();
+                    drop((conn, guard));
+                }
+
+                // wait for 1 second
+                ready!(shutdown.timer.as_mut().poll(cx));
+
+                if this.counter.total() == 0 {
+                    // graceful shutdown
+                    if let WorkerState::Shutdown(shutdown) = mem::take(&mut this.state) {
+                        let _ = shutdown.tx.send(true);
+                    }
+
+                    Poll::Ready(())
+                } else if shutdown.start_from.elapsed() >= this.shutdown_timeout {
+                    // timeout forceful shutdown
+                    if let WorkerState::Shutdown(shutdown) = mem::take(&mut this.state) {
+                        let _ = shutdown.tx.send(false);
+                    }
+
+                    Poll::Ready(())
+                } else {
+                    // reset timer and wait for 1 second
+                    let time = Instant::now() + Duration::from_secs(1);
+                    shutdown.timer.as_mut().reset(time);
+                    shutdown.timer.as_mut().poll(cx)
+                }
+            }
+
+            // actively poll stream and handle worker command
+            WorkerState::Available => loop {
+                match this.check_readiness(cx) {
+                    Ok(true) => {}
+                    Ok(false) => {
+                        trace!("worker is unavailable");
+                        this.state = WorkerState::Unavailable;
+                        return self.poll(cx);
+                    }
+                    Err((token, idx)) => {
+                        this.restart_service(token, idx);
+                        return self.poll(cx);
+                    }
+                }
+
+                // handle incoming io stream
+                match ready!(this.conn_rx.poll_recv(cx)) {
+                    Some(msg) => {
+                        let guard = this.counter.guard();
+                        let _ = this.services[msg.token]
+                            .service
+                            .call((guard, msg.io))
+                            .into_inner();
+                    }
+                    None => return Poll::Ready(()),
+                };
+            },
+        }
+    }
+}
+
+fn wrap_worker_services(services: Vec<(usize, usize, BoxedServerService)>) -> Vec<WorkerService> {
+    services
+        .into_iter()
+        .fold(Vec::new(), |mut services, (idx, token, service)| {
+            assert_eq!(token, services.len());
+            services.push(WorkerService {
+                factory_idx: idx,
+                service,
+                status: WorkerServiceStatus::Unavailable,
+            });
+            services
+        })
+}
+
\ No newline at end of file diff --git a/src/actix_service/and_then.rs.html b/src/actix_service/and_then.rs.html new file mode 100644 index 00000000..f119a2a6 --- /dev/null +++ b/src/actix_service/and_then.rs.html @@ -0,0 +1,651 @@ +and_then.rs - source

actix_service/
and_then.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
use alloc::rc::Rc;
+use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use futures_core::ready;
+use pin_project_lite::pin_project;
+
+use super::{Service, ServiceFactory};
+
+/// Service for the `and_then` combinator, chaining a computation onto the end of another service
+/// which completes successfully.
+///
+/// This is created by the `Pipeline::and_then` method.
+pub struct AndThenService<A, B, Req>(Rc<(A, B)>, PhantomData<Req>);
+
+impl<A, B, Req> AndThenService<A, B, Req> {
+    /// Create new `AndThen` combinator
+    pub(crate) fn new(a: A, b: B) -> Self
+    where
+        A: Service<Req>,
+        B: Service<A::Response, Error = A::Error>,
+    {
+        Self(Rc::new((a, b)), PhantomData)
+    }
+}
+
+impl<A, B, Req> Clone for AndThenService<A, B, Req> {
+    fn clone(&self) -> Self {
+        AndThenService(self.0.clone(), PhantomData)
+    }
+}
+
+impl<A, B, Req> Service<Req> for AndThenService<A, B, Req>
+where
+    A: Service<Req>,
+    B: Service<A::Response, Error = A::Error>,
+{
+    type Response = B::Response;
+    type Error = A::Error;
+    type Future = AndThenServiceResponse<A, B, Req>;
+
+    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        let (a, b) = &*self.0;
+        let not_ready = !a.poll_ready(cx)?.is_ready();
+        if !b.poll_ready(cx)?.is_ready() || not_ready {
+            Poll::Pending
+        } else {
+            Poll::Ready(Ok(()))
+        }
+    }
+
+    fn call(&self, req: Req) -> Self::Future {
+        AndThenServiceResponse {
+            state: State::A {
+                fut: self.0 .0.call(req),
+                b: Some(self.0.clone()),
+            },
+        }
+    }
+}
+
+pin_project! {
+    pub struct AndThenServiceResponse<A, B, Req>
+    where
+        A: Service<Req>,
+        B: Service<A::Response, Error = A::Error>,
+    {
+        #[pin]
+        state: State<A, B, Req>,
+    }
+}
+
+pin_project! {
+    #[project = StateProj]
+    enum State<A, B, Req>
+    where
+        A: Service<Req>,
+        B: Service<A::Response, Error = A::Error>,
+    {
+        A {
+            #[pin]
+            fut: A::Future,
+            b: Option<Rc<(A, B)>>,
+        },
+        B {
+            #[pin]
+            fut: B::Future,
+        },
+    }
+}
+
+impl<A, B, Req> Future for AndThenServiceResponse<A, B, Req>
+where
+    A: Service<Req>,
+    B: Service<A::Response, Error = A::Error>,
+{
+    type Output = Result<B::Response, A::Error>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.as_mut().project();
+
+        match this.state.as_mut().project() {
+            StateProj::A { fut, b } => {
+                let res = ready!(fut.poll(cx))?;
+                let b = b.take().unwrap();
+                let fut = b.1.call(res);
+                this.state.set(State::B { fut });
+                self.poll(cx)
+            }
+            StateProj::B { fut } => fut.poll(cx),
+        }
+    }
+}
+
+/// `.and_then()` service factory combinator
+pub struct AndThenServiceFactory<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    A::Config: Clone,
+    B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
+{
+    inner: Rc<(A, B)>,
+    _phantom: PhantomData<Req>,
+}
+
+impl<A, B, Req> AndThenServiceFactory<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    A::Config: Clone,
+    B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
+{
+    /// Create new `AndThenFactory` combinator
+    pub(crate) fn new(a: A, b: B) -> Self {
+        Self {
+            inner: Rc::new((a, b)),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<A, B, Req> ServiceFactory<Req> for AndThenServiceFactory<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    A::Config: Clone,
+    B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
+{
+    type Response = B::Response;
+    type Error = A::Error;
+
+    type Config = A::Config;
+    type Service = AndThenService<A::Service, B::Service, Req>;
+    type InitError = A::InitError;
+    type Future = AndThenServiceFactoryResponse<A, B, Req>;
+
+    fn new_service(&self, cfg: A::Config) -> Self::Future {
+        let inner = &*self.inner;
+        AndThenServiceFactoryResponse::new(
+            inner.0.new_service(cfg.clone()),
+            inner.1.new_service(cfg),
+        )
+    }
+}
+
+impl<A, B, Req> Clone for AndThenServiceFactory<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    A::Config: Clone,
+    B: ServiceFactory<A::Response, Config = A::Config, Error = A::Error, InitError = A::InitError>,
+{
+    fn clone(&self) -> Self {
+        Self {
+            inner: self.inner.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+pin_project! {
+    pub struct AndThenServiceFactoryResponse<A, B, Req>
+    where
+        A: ServiceFactory<Req>,
+        B: ServiceFactory<A::Response>,
+    {
+        #[pin]
+        fut_a: A::Future,
+        #[pin]
+        fut_b: B::Future,
+
+        a: Option<A::Service>,
+        b: Option<B::Service>,
+    }
+}
+
+impl<A, B, Req> AndThenServiceFactoryResponse<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    B: ServiceFactory<A::Response>,
+{
+    fn new(fut_a: A::Future, fut_b: B::Future) -> Self {
+        AndThenServiceFactoryResponse {
+            fut_a,
+            fut_b,
+            a: None,
+            b: None,
+        }
+    }
+}
+
+impl<A, B, Req> Future for AndThenServiceFactoryResponse<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    B: ServiceFactory<A::Response, Error = A::Error, InitError = A::InitError>,
+{
+    type Output = Result<AndThenService<A::Service, B::Service, Req>, A::InitError>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+
+        if this.a.is_none() {
+            if let Poll::Ready(service) = this.fut_a.poll(cx)? {
+                *this.a = Some(service);
+            }
+        }
+        if this.b.is_none() {
+            if let Poll::Ready(service) = this.fut_b.poll(cx)? {
+                *this.b = Some(service);
+            }
+        }
+        if this.a.is_some() && this.b.is_some() {
+            Poll::Ready(Ok(AndThenService::new(
+                this.a.take().unwrap(),
+                this.b.take().unwrap(),
+            )))
+        } else {
+            Poll::Pending
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use alloc::rc::Rc;
+    use core::{
+        cell::Cell,
+        task::{Context, Poll},
+    };
+
+    use futures_util::future::lazy;
+
+    use crate::{
+        fn_factory, ok,
+        pipeline::{pipeline, pipeline_factory},
+        ready, Ready, Service, ServiceFactory,
+    };
+
+    struct Srv1(Rc<Cell<usize>>);
+
+    impl Service<&'static str> for Srv1 {
+        type Response = &'static str;
+        type Error = ();
+        type Future = Ready<Result<Self::Response, ()>>;
+
+        fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+            self.0.set(self.0.get() + 1);
+            Poll::Ready(Ok(()))
+        }
+
+        fn call(&self, req: &'static str) -> Self::Future {
+            ok(req)
+        }
+    }
+
+    #[derive(Clone)]
+    struct Srv2(Rc<Cell<usize>>);
+
+    impl Service<&'static str> for Srv2 {
+        type Response = (&'static str, &'static str);
+        type Error = ();
+        type Future = Ready<Result<Self::Response, ()>>;
+
+        fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+            self.0.set(self.0.get() + 1);
+            Poll::Ready(Ok(()))
+        }
+
+        fn call(&self, req: &'static str) -> Self::Future {
+            ok((req, "srv2"))
+        }
+    }
+
+    #[actix_rt::test]
+    async fn test_poll_ready() {
+        let cnt = Rc::new(Cell::new(0));
+        let srv = pipeline(Srv1(cnt.clone())).and_then(Srv2(cnt.clone()));
+        let res = lazy(|cx| srv.poll_ready(cx)).await;
+        assert_eq!(res, Poll::Ready(Ok(())));
+        assert_eq!(cnt.get(), 2);
+    }
+
+    #[actix_rt::test]
+    async fn test_call() {
+        let cnt = Rc::new(Cell::new(0));
+        let srv = pipeline(Srv1(cnt.clone())).and_then(Srv2(cnt));
+        let res = srv.call("srv1").await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv1", "srv2"));
+    }
+
+    #[actix_rt::test]
+    async fn test_new_service() {
+        let cnt = Rc::new(Cell::new(0));
+        let cnt2 = cnt.clone();
+        let new_srv = pipeline_factory(fn_factory(move || ready(Ok::<_, ()>(Srv1(cnt2.clone())))))
+            .and_then(move || ready(Ok(Srv2(cnt.clone()))));
+
+        let srv = new_srv.new_service(()).await.unwrap();
+        let res = srv.call("srv1").await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv1", "srv2"));
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/apply.rs.html b/src/actix_service/apply.rs.html new file mode 100644 index 00000000..e8aa7d7b --- /dev/null +++ b/src/actix_service/apply.rs.html @@ -0,0 +1,547 @@ +apply.rs - source

actix_service/
apply.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use futures_core::ready;
+use pin_project_lite::pin_project;
+
+use super::{IntoService, IntoServiceFactory, Service, ServiceFactory};
+
+/// Apply transform function to a service.
+///
+/// The In and Out type params refer to the request and response types for the wrapped service.
+pub fn apply_fn<I, S, F, Fut, Req, In, Res, Err>(
+    service: I,
+    wrap_fn: F,
+) -> Apply<S, F, Req, In, Res, Err>
+where
+    I: IntoService<S, In>,
+    S: Service<In, Error = Err>,
+    F: Fn(Req, &S) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    Apply::new(service.into_service(), wrap_fn)
+}
+
+/// Service factory that produces `apply_fn` service.
+///
+/// The In and Out type params refer to the request and response types for the wrapped service.
+pub fn apply_fn_factory<I, SF, F, Fut, Req, In, Res, Err>(
+    service: I,
+    f: F,
+) -> ApplyFactory<SF, F, Req, In, Res, Err>
+where
+    I: IntoServiceFactory<SF, In>,
+    SF: ServiceFactory<In, Error = Err>,
+    F: Fn(Req, &SF::Service) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    ApplyFactory::new(service.into_factory(), f)
+}
+
+/// `Apply` service combinator.
+///
+/// The In and Out type params refer to the request and response types for the wrapped service.
+pub struct Apply<S, F, Req, In, Res, Err>
+where
+    S: Service<In, Error = Err>,
+{
+    service: S,
+    wrap_fn: F,
+    _phantom: PhantomData<fn(Req) -> (In, Res, Err)>,
+}
+
+impl<S, F, Fut, Req, In, Res, Err> Apply<S, F, Req, In, Res, Err>
+where
+    S: Service<In, Error = Err>,
+    F: Fn(Req, &S) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    /// Create new `Apply` combinator
+    fn new(service: S, wrap_fn: F) -> Self {
+        Self {
+            service,
+            wrap_fn,
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<S, F, Fut, Req, In, Res, Err> Clone for Apply<S, F, Req, In, Res, Err>
+where
+    S: Service<In, Error = Err> + Clone,
+    F: Fn(Req, &S) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn clone(&self) -> Self {
+        Apply {
+            service: self.service.clone(),
+            wrap_fn: self.wrap_fn.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<S, F, Fut, Req, In, Res, Err> Service<Req> for Apply<S, F, Req, In, Res, Err>
+where
+    S: Service<In, Error = Err>,
+    F: Fn(Req, &S) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    type Response = Res;
+    type Error = Err;
+    type Future = Fut;
+
+    crate::forward_ready!(service);
+
+    fn call(&self, req: Req) -> Self::Future {
+        (self.wrap_fn)(req, &self.service)
+    }
+}
+
+/// `ApplyFactory` service factory combinator.
+pub struct ApplyFactory<SF, F, Req, In, Res, Err> {
+    factory: SF,
+    wrap_fn: F,
+    _phantom: PhantomData<fn(Req) -> (In, Res, Err)>,
+}
+
+impl<SF, F, Fut, Req, In, Res, Err> ApplyFactory<SF, F, Req, In, Res, Err>
+where
+    SF: ServiceFactory<In, Error = Err>,
+    F: Fn(Req, &SF::Service) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    /// Create new `ApplyFactory` new service instance
+    fn new(factory: SF, wrap_fn: F) -> Self {
+        Self {
+            factory,
+            wrap_fn,
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<SF, F, Fut, Req, In, Res, Err> Clone for ApplyFactory<SF, F, Req, In, Res, Err>
+where
+    SF: ServiceFactory<In, Error = Err> + Clone,
+    F: Fn(Req, &SF::Service) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn clone(&self) -> Self {
+        Self {
+            factory: self.factory.clone(),
+            wrap_fn: self.wrap_fn.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<SF, F, Fut, Req, In, Res, Err> ServiceFactory<Req> for ApplyFactory<SF, F, Req, In, Res, Err>
+where
+    SF: ServiceFactory<In, Error = Err>,
+    F: Fn(Req, &SF::Service) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    type Response = Res;
+    type Error = Err;
+
+    type Config = SF::Config;
+    type Service = Apply<SF::Service, F, Req, In, Res, Err>;
+    type InitError = SF::InitError;
+    type Future = ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>;
+
+    fn new_service(&self, cfg: SF::Config) -> Self::Future {
+        let svc = self.factory.new_service(cfg);
+        ApplyServiceFactoryResponse::new(svc, self.wrap_fn.clone())
+    }
+}
+
+pin_project! {
+    pub struct ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
+    where
+        SF: ServiceFactory<In, Error = Err>,
+        F: Fn(Req, &SF::Service) -> Fut,
+        Fut: Future<Output = Result<Res, Err>>,
+    {
+        #[pin]
+        fut: SF::Future,
+        wrap_fn: Option<F>,
+        _phantom: PhantomData<fn(Req) -> Res>,
+    }
+}
+
+impl<SF, F, Fut, Req, In, Res, Err> ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
+where
+    SF: ServiceFactory<In, Error = Err>,
+    F: Fn(Req, &SF::Service) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn new(fut: SF::Future, wrap_fn: F) -> Self {
+        Self {
+            fut,
+            wrap_fn: Some(wrap_fn),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<SF, F, Fut, Req, In, Res, Err> Future
+    for ApplyServiceFactoryResponse<SF, F, Fut, Req, In, Res, Err>
+where
+    SF: ServiceFactory<In, Error = Err>,
+    F: Fn(Req, &SF::Service) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    type Output = Result<Apply<SF::Service, F, Req, In, Res, Err>, SF::InitError>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+
+        let svc = ready!(this.fut.poll(cx))?;
+        Poll::Ready(Ok(Apply::new(svc, this.wrap_fn.take().unwrap())))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use futures_util::future::lazy;
+
+    use super::*;
+    use crate::{
+        ok,
+        pipeline::{pipeline, pipeline_factory},
+        Ready,
+    };
+
+    #[derive(Clone)]
+    struct Srv;
+
+    impl Service<()> for Srv {
+        type Response = ();
+        type Error = ();
+        type Future = Ready<Result<(), ()>>;
+
+        crate::always_ready!();
+
+        fn call(&self, _: ()) -> Self::Future {
+            ok(())
+        }
+    }
+
+    #[actix_rt::test]
+    async fn test_call() {
+        let srv = pipeline(apply_fn(Srv, |req: &'static str, srv| {
+            let fut = srv.call(());
+            async move {
+                fut.await.unwrap();
+                Ok((req, ()))
+            }
+        }));
+
+        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
+
+        let res = srv.call("srv").await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv", ()));
+    }
+
+    #[actix_rt::test]
+    async fn test_new_service() {
+        let new_srv = pipeline_factory(apply_fn_factory(
+            || ok::<_, ()>(Srv),
+            |req: &'static str, srv| {
+                let fut = srv.call(());
+                async move {
+                    fut.await.unwrap();
+                    Ok((req, ()))
+                }
+            },
+        ));
+
+        let srv = new_srv.new_service(()).await.unwrap();
+
+        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
+
+        let res = srv.call("srv").await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv", ()));
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/apply_cfg.rs.html b/src/actix_service/apply_cfg.rs.html new file mode 100644 index 00000000..95ae8e5c --- /dev/null +++ b/src/actix_service/apply_cfg.rs.html @@ -0,0 +1,465 @@ +apply_cfg.rs - source

actix_service/
apply_cfg.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
use alloc::rc::Rc;
+use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use futures_core::ready;
+use pin_project_lite::pin_project;
+
+use crate::{Service, ServiceFactory};
+
+/// Convert `Fn(Config, &Service1) -> Future<Service2>` fn to a service factory.
+pub fn apply_cfg<S1, Req, F, Cfg, Fut, S2, Err>(
+    srv: S1,
+    f: F,
+) -> impl ServiceFactory<
+    Req,
+    Config = Cfg,
+    Response = S2::Response,
+    Error = S2::Error,
+    Service = S2,
+    InitError = Err,
+    Future = Fut,
+> + Clone
+where
+    S1: Service<Req>,
+    F: Fn(Cfg, &S1) -> Fut,
+    Fut: Future<Output = Result<S2, Err>>,
+    S2: Service<Req>,
+{
+    ApplyConfigService {
+        srv: Rc::new((srv, f)),
+        _phantom: PhantomData,
+    }
+}
+
+/// Convert `Fn(Config, &ServiceFactory1) -> Future<ServiceFactory2>` fn to a service factory.
+///
+/// Service1 get constructed from `T` factory.
+pub fn apply_cfg_factory<SF, Req, F, Cfg, Fut, S>(
+    factory: SF,
+    f: F,
+) -> impl ServiceFactory<
+    Req,
+    Config = Cfg,
+    Response = S::Response,
+    Error = S::Error,
+    Service = S,
+    InitError = SF::InitError,
+> + Clone
+where
+    SF: ServiceFactory<Req, Config = ()>,
+    F: Fn(Cfg, &SF::Service) -> Fut,
+    SF::InitError: From<SF::Error>,
+    Fut: Future<Output = Result<S, SF::InitError>>,
+    S: Service<Req>,
+{
+    ApplyConfigServiceFactory {
+        srv: Rc::new((factory, f)),
+        _phantom: PhantomData,
+    }
+}
+
+/// Convert `Fn(Config, &Server) -> Future<Service>` fn to NewService\
+struct ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
+where
+    S1: Service<Req>,
+    F: Fn(Cfg, &S1) -> Fut,
+    Fut: Future<Output = Result<S2, Err>>,
+    S2: Service<Req>,
+{
+    srv: Rc<(S1, F)>,
+    _phantom: PhantomData<(Cfg, Req, Fut, S2)>,
+}
+
+impl<S1, Req, F, Cfg, Fut, S2, Err> Clone for ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
+where
+    S1: Service<Req>,
+    F: Fn(Cfg, &S1) -> Fut,
+    Fut: Future<Output = Result<S2, Err>>,
+    S2: Service<Req>,
+{
+    fn clone(&self) -> Self {
+        ApplyConfigService {
+            srv: self.srv.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<S1, Req, F, Cfg, Fut, S2, Err> ServiceFactory<Req>
+    for ApplyConfigService<S1, Req, F, Cfg, Fut, S2, Err>
+where
+    S1: Service<Req>,
+    F: Fn(Cfg, &S1) -> Fut,
+    Fut: Future<Output = Result<S2, Err>>,
+    S2: Service<Req>,
+{
+    type Response = S2::Response;
+    type Error = S2::Error;
+    type Config = Cfg;
+    type Service = S2;
+
+    type InitError = Err;
+    type Future = Fut;
+
+    fn new_service(&self, cfg: Cfg) -> Self::Future {
+        let (t, f) = &*self.srv;
+        f(cfg, t)
+    }
+}
+
+/// Convert `Fn(&Config) -> Future<Service>` fn to NewService
+struct ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
+where
+    SF: ServiceFactory<Req, Config = ()>,
+    F: Fn(Cfg, &SF::Service) -> Fut,
+    Fut: Future<Output = Result<S, SF::InitError>>,
+    S: Service<Req>,
+{
+    srv: Rc<(SF, F)>,
+    _phantom: PhantomData<(Cfg, Req, Fut, S)>,
+}
+
+impl<SF, Req, F, Cfg, Fut, S> Clone for ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
+where
+    SF: ServiceFactory<Req, Config = ()>,
+    F: Fn(Cfg, &SF::Service) -> Fut,
+    Fut: Future<Output = Result<S, SF::InitError>>,
+    S: Service<Req>,
+{
+    fn clone(&self) -> Self {
+        Self {
+            srv: self.srv.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<SF, Req, F, Cfg, Fut, S> ServiceFactory<Req>
+    for ApplyConfigServiceFactory<SF, Req, F, Cfg, Fut, S>
+where
+    SF: ServiceFactory<Req, Config = ()>,
+    SF::InitError: From<SF::Error>,
+    F: Fn(Cfg, &SF::Service) -> Fut,
+    Fut: Future<Output = Result<S, SF::InitError>>,
+    S: Service<Req>,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Config = Cfg;
+    type Service = S;
+
+    type InitError = SF::InitError;
+    type Future = ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>;
+
+    fn new_service(&self, cfg: Cfg) -> Self::Future {
+        ApplyConfigServiceFactoryResponse {
+            cfg: Some(cfg),
+            store: self.srv.clone(),
+            state: State::A {
+                fut: self.srv.0.new_service(()),
+            },
+        }
+    }
+}
+
+pin_project! {
+    struct ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
+    where
+        SF: ServiceFactory<Req, Config = ()>,
+        SF::InitError: From<SF::Error>,
+        F: Fn(Cfg, &SF::Service) -> Fut,
+        Fut: Future<Output = Result<S, SF::InitError>>,
+        S: Service<Req>,
+    {
+        cfg: Option<Cfg>,
+        store: Rc<(SF, F)>,
+        #[pin]
+        state: State<SF, Fut, S, Req>,
+    }
+}
+
+pin_project! {
+    #[project = StateProj]
+    enum State<SF, Fut, S, Req>
+    where
+        SF: ServiceFactory<Req, Config = ()>,
+        SF::InitError: From<SF::Error>,
+        Fut: Future<Output = Result<S, SF::InitError>>,
+        S: Service<Req>,
+    {
+        A { #[pin] fut: SF::Future },
+        B { svc: SF::Service },
+        C { #[pin] fut: Fut },
+    }
+}
+
+impl<SF, Req, F, Cfg, Fut, S> Future for ApplyConfigServiceFactoryResponse<SF, Req, F, Cfg, Fut, S>
+where
+    SF: ServiceFactory<Req, Config = ()>,
+    SF::InitError: From<SF::Error>,
+    F: Fn(Cfg, &SF::Service) -> Fut,
+    Fut: Future<Output = Result<S, SF::InitError>>,
+    S: Service<Req>,
+{
+    type Output = Result<S, SF::InitError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.as_mut().project();
+
+        match this.state.as_mut().project() {
+            StateProj::A { fut } => {
+                let svc = ready!(fut.poll(cx))?;
+                this.state.set(State::B { svc });
+                self.poll(cx)
+            }
+            StateProj::B { svc } => {
+                ready!(svc.poll_ready(cx))?;
+                {
+                    let (_, f) = &**this.store;
+                    let fut = f(this.cfg.take().unwrap(), svc);
+                    this.state.set(State::C { fut });
+                }
+                self.poll(cx)
+            }
+            StateProj::C { fut } => fut.poll(cx),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/boxed.rs.html b/src/actix_service/boxed.rs.html new file mode 100644 index 00000000..9197e432 --- /dev/null +++ b/src/actix_service/boxed.rs.html @@ -0,0 +1,277 @@ +boxed.rs - source

actix_service/
boxed.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
//! Trait object forms of services and service factories.
+
+use alloc::{boxed::Box, rc::Rc};
+use core::{future::Future, pin::Pin};
+
+use paste::paste;
+
+use crate::{Service, ServiceFactory};
+
+/// A boxed future with no send bound or lifetime parameters.
+pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
+
+macro_rules! service_object {
+    ($name: ident, $type: tt, $fn_name: ident) => {
+        paste! {
+            #[doc = "Type alias for service trait object using `" $type "`."]
+            pub type $name<Req, Res, Err> = $type<
+                dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>,
+            >;
+
+            #[doc = "Wraps service as a trait object using [`" $name "`]."]
+            pub fn $fn_name<S, Req>(service: S) -> $name<Req, S::Response, S::Error>
+            where
+                S: Service<Req> + 'static,
+                Req: 'static,
+                S::Future: 'static,
+            {
+                $type::new(ServiceWrapper::new(service))
+            }
+        }
+    };
+}
+
+service_object!(BoxService, Box, service);
+service_object!(RcService, Rc, rc_service);
+
+struct ServiceWrapper<S> {
+    inner: S,
+}
+
+impl<S> ServiceWrapper<S> {
+    fn new(inner: S) -> Self {
+        Self { inner }
+    }
+}
+
+impl<S, Req, Res, Err> Service<Req> for ServiceWrapper<S>
+where
+    S: Service<Req, Response = Res, Error = Err>,
+    S::Future: 'static,
+{
+    type Response = Res;
+    type Error = Err;
+    type Future = BoxFuture<Result<Res, Err>>;
+
+    crate::forward_ready!(inner);
+
+    fn call(&self, req: Req) -> Self::Future {
+        Box::pin(self.inner.call(req))
+    }
+}
+
+/// Wrapper for a service factory that will map it's services to boxed trait object services.
+pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>);
+
+/// Wraps a service factory that returns service trait objects.
+pub fn factory<SF, Req>(
+    factory: SF,
+) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error, SF::InitError>
+where
+    SF: ServiceFactory<Req> + 'static,
+    Req: 'static,
+    SF::Response: 'static,
+    SF::Service: 'static,
+    SF::Future: 'static,
+    SF::Error: 'static,
+    SF::InitError: 'static,
+{
+    BoxServiceFactory(Box::new(FactoryWrapper(factory)))
+}
+
+type Inner<C, Req, Res, Err, InitErr> = Box<
+    dyn ServiceFactory<
+        Req,
+        Config = C,
+        Response = Res,
+        Error = Err,
+        InitError = InitErr,
+        Service = BoxService<Req, Res, Err>,
+        Future = BoxFuture<Result<BoxService<Req, Res, Err>, InitErr>>,
+    >,
+>;
+
+impl<C, Req, Res, Err, InitErr> ServiceFactory<Req> for BoxServiceFactory<C, Req, Res, Err, InitErr>
+where
+    Req: 'static,
+    Res: 'static,
+    Err: 'static,
+    InitErr: 'static,
+{
+    type Response = Res;
+    type Error = Err;
+    type Config = C;
+    type Service = BoxService<Req, Res, Err>;
+    type InitError = InitErr;
+
+    type Future = BoxFuture<Result<Self::Service, InitErr>>;
+
+    fn new_service(&self, cfg: C) -> Self::Future {
+        self.0.new_service(cfg)
+    }
+}
+
+struct FactoryWrapper<SF>(SF);
+
+impl<SF, Req, Cfg, Res, Err, InitErr> ServiceFactory<Req> for FactoryWrapper<SF>
+where
+    Req: 'static,
+    Res: 'static,
+    Err: 'static,
+    InitErr: 'static,
+    SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err, InitError = InitErr>,
+    SF::Future: 'static,
+    SF::Service: 'static,
+    <SF::Service as Service<Req>>::Future: 'static,
+{
+    type Response = Res;
+    type Error = Err;
+    type Config = Cfg;
+    type Service = BoxService<Req, Res, Err>;
+    type InitError = InitErr;
+    type Future = BoxFuture<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, cfg: Cfg) -> Self::Future {
+        let f = self.0.new_service(cfg);
+        Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as _) })
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/ext.rs.html b/src/actix_service/ext.rs.html new file mode 100644 index 00000000..44aba5da --- /dev/null +++ b/src/actix_service/ext.rs.html @@ -0,0 +1,249 @@ +ext.rs - source

actix_service/
ext.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
use crate::{
+    and_then::{AndThenService, AndThenServiceFactory},
+    map::Map,
+    map_err::MapErr,
+    transform_err::TransformMapInitErr,
+    IntoService, IntoServiceFactory, Service, ServiceFactory, Transform,
+};
+
+/// An extension trait for [`Service`]s that provides a variety of convenient adapters.
+pub trait ServiceExt<Req>: Service<Req> {
+    /// Map this service's output to a different type, returning a new service
+    /// of the resulting type.
+    ///
+    /// This function is similar to the `Option::map` or `Iterator::map` where
+    /// it will change the type of the underlying service.
+    ///
+    /// Note that this function consumes the receiving service and returns a
+    /// wrapped version of it, similar to the existing `map` methods in the
+    /// standard library.
+    fn map<F, R>(self, f: F) -> Map<Self, F, Req, R>
+    where
+        Self: Sized,
+        F: FnMut(Self::Response) -> R,
+    {
+        Map::new(self, f)
+    }
+
+    /// Map this service's error to a different error, returning a new service.
+    ///
+    /// This function is similar to the `Result::map_err` where it will change
+    /// the error type of the underlying service. For example, this can be useful to
+    /// ensure that services have the same error type.
+    ///
+    /// Note that this function consumes the receiving service and returns a
+    /// wrapped version of it.
+    fn map_err<F, E>(self, f: F) -> MapErr<Self, Req, F, E>
+    where
+        Self: Sized,
+        F: Fn(Self::Error) -> E,
+    {
+        MapErr::new(self, f)
+    }
+
+    /// Call another service after call to this one has resolved successfully.
+    ///
+    /// This function can be used to chain two services together and ensure that the second service
+    /// isn't called until call to the first service have finished. Result of the call to the first
+    /// service is used as an input parameter for the second service's call.
+    ///
+    /// Note that this function consumes the receiving service and returns a wrapped version of it.
+    fn and_then<I, S1>(self, service: I) -> AndThenService<Self, S1, Req>
+    where
+        Self: Sized,
+        I: IntoService<S1, Self::Response>,
+        S1: Service<Self::Response, Error = Self::Error>,
+    {
+        AndThenService::new(self, service.into_service())
+    }
+}
+
+impl<S, Req> ServiceExt<Req> for S where S: Service<Req> {}
+
+/// An extension trait for [`ServiceFactory`]s that provides a variety of convenient adapters.
+pub trait ServiceFactoryExt<Req>: ServiceFactory<Req> {
+    /// Map this service's output to a different type, returning a new service
+    /// of the resulting type.
+    fn map<F, R>(self, f: F) -> crate::map::MapServiceFactory<Self, F, Req, R>
+    where
+        Self: Sized,
+        F: FnMut(Self::Response) -> R + Clone,
+    {
+        crate::map::MapServiceFactory::new(self, f)
+    }
+
+    /// Map this service's error to a different error, returning a new service.
+    fn map_err<F, E>(self, f: F) -> crate::map_err::MapErrServiceFactory<Self, Req, F, E>
+    where
+        Self: Sized,
+        F: Fn(Self::Error) -> E + Clone,
+    {
+        crate::map_err::MapErrServiceFactory::new(self, f)
+    }
+
+    /// Map this factory's init error to a different error, returning a new service.
+    fn map_init_err<F, E>(self, f: F) -> crate::map_init_err::MapInitErr<Self, F, Req, E>
+    where
+        Self: Sized,
+        F: Fn(Self::InitError) -> E + Clone,
+    {
+        crate::map_init_err::MapInitErr::new(self, f)
+    }
+
+    /// Call another service after call to this one has resolved successfully.
+    fn and_then<I, SF1>(self, factory: I) -> AndThenServiceFactory<Self, SF1, Req>
+    where
+        Self: Sized,
+        Self::Config: Clone,
+        I: IntoServiceFactory<SF1, Self::Response>,
+        SF1: ServiceFactory<
+            Self::Response,
+            Config = Self::Config,
+            Error = Self::Error,
+            InitError = Self::InitError,
+        >,
+    {
+        AndThenServiceFactory::new(self, factory.into_factory())
+    }
+}
+
+impl<SF, Req> ServiceFactoryExt<Req> for SF where SF: ServiceFactory<Req> {}
+
+/// An extension trait for [`Transform`]s that provides a variety of convenient adapters.
+pub trait TransformExt<S, Req>: Transform<S, Req> {
+    /// Return a new `Transform` whose init error is mapped to to a different type.
+    fn map_init_err<F, E>(self, f: F) -> TransformMapInitErr<Self, S, Req, F, E>
+    where
+        Self: Sized,
+        F: Fn(Self::InitError) -> E + Clone,
+    {
+        TransformMapInitErr::new(self, f)
+    }
+}
+
+impl<T, Req> TransformExt<T, Req> for T where T: Transform<T, Req> {}
+
\ No newline at end of file diff --git a/src/actix_service/fn_service.rs.html b/src/actix_service/fn_service.rs.html new file mode 100644 index 00000000..ac8755ef --- /dev/null +++ b/src/actix_service/fn_service.rs.html @@ -0,0 +1,849 @@ +fn_service.rs - source

actix_service/
fn_service.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
use core::{future::Future, marker::PhantomData};
+
+use crate::{ok, IntoService, IntoServiceFactory, Ready, Service, ServiceFactory};
+
+/// Create `ServiceFactory` for function that can act as a `Service`
+pub fn fn_service<F, Fut, Req, Res, Err, Cfg>(f: F) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
+where
+    F: Fn(Req) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    FnServiceFactory::new(f)
+}
+
+/// Create `ServiceFactory` for function that can produce services
+///
+/// # Examples
+/// ```
+/// use std::io;
+/// use actix_service::{fn_factory, fn_service, Service, ServiceFactory};
+/// use futures_util::future::ok;
+///
+/// /// Service that divides two usize values.
+/// async fn div((x, y): (usize, usize)) -> Result<usize, io::Error> {
+///     if y == 0 {
+///         Err(io::Error::new(io::ErrorKind::Other, "divide by zero"))
+///     } else {
+///         Ok(x / y)
+///     }
+/// }
+///
+/// #[actix_rt::main]
+/// async fn main() -> io::Result<()> {
+///     // Create service factory that produces `div` services
+///     let factory = fn_factory(|| {
+///         ok::<_, io::Error>(fn_service(div))
+///     });
+///
+///     // construct new service
+///     let srv = factory.new_service(()).await?;
+///
+///     // now we can use `div` service
+///     let result = srv.call((10, 20)).await?;
+///
+///     println!("10 / 20 = {}", result);
+///
+///     Ok(())
+/// }
+/// ```
+pub fn fn_factory<F, Cfg, Srv, Req, Fut, Err>(f: F) -> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
+where
+    F: Fn() -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    FnServiceNoConfig::new(f)
+}
+
+/// Create `ServiceFactory` for function that accepts config argument and can produce services
+///
+/// Any function that has following form `Fn(Config) -> Future<Output = Service>` could act as
+/// a `ServiceFactory`.
+///
+/// # Examples
+/// ```
+/// use std::io;
+/// use actix_service::{fn_factory_with_config, fn_service, Service, ServiceFactory};
+/// use futures_util::future::ok;
+///
+/// #[actix_rt::main]
+/// async fn main() -> io::Result<()> {
+///     // Create service factory. factory uses config argument for
+///     // services it generates.
+///     let factory = fn_factory_with_config(|y: usize| {
+///         ok::<_, io::Error>(fn_service(move |x: usize| ok::<_, io::Error>(x * y)))
+///     });
+///
+///     // construct new service with config argument
+///     let srv = factory.new_service(10).await?;
+///
+///     let result = srv.call(10).await?;
+///     assert_eq!(result, 100);
+///
+///     println!("10 * 10 = {}", result);
+///     Ok(())
+/// }
+/// ```
+pub fn fn_factory_with_config<F, Fut, Cfg, Srv, Req, Err>(
+    f: F,
+) -> FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
+where
+    F: Fn(Cfg) -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    FnServiceConfig::new(f)
+}
+
+pub struct FnService<F, Fut, Req, Res, Err>
+where
+    F: FnMut(Req) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    f: F,
+    _t: PhantomData<fn(Req)>,
+}
+
+impl<F, Fut, Req, Res, Err> FnService<F, Fut, Req, Res, Err>
+where
+    F: FnMut(Req) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    pub(crate) fn new(f: F) -> Self {
+        Self { f, _t: PhantomData }
+    }
+}
+
+impl<F, Fut, Req, Res, Err> Clone for FnService<F, Fut, Req, Res, Err>
+where
+    F: FnMut(Req) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn clone(&self) -> Self {
+        Self::new(self.f.clone())
+    }
+}
+
+impl<F, Fut, Req, Res, Err> Service<Req> for FnService<F, Fut, Req, Res, Err>
+where
+    F: Fn(Req) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    type Response = Res;
+    type Error = Err;
+    type Future = Fut;
+
+    crate::always_ready!();
+
+    fn call(&self, req: Req) -> Self::Future {
+        (self.f)(req)
+    }
+}
+
+impl<F, Fut, Req, Res, Err> IntoService<FnService<F, Fut, Req, Res, Err>, Req> for F
+where
+    F: Fn(Req) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn into_service(self) -> FnService<F, Fut, Req, Res, Err> {
+        FnService::new(self)
+    }
+}
+
+pub struct FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
+where
+    F: Fn(Req) -> Fut,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    f: F,
+    _t: PhantomData<fn(Req, Cfg)>,
+}
+
+impl<F, Fut, Req, Res, Err, Cfg> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
+where
+    F: Fn(Req) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn new(f: F) -> Self {
+        FnServiceFactory { f, _t: PhantomData }
+    }
+}
+
+impl<F, Fut, Req, Res, Err, Cfg> Clone for FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
+where
+    F: Fn(Req) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn clone(&self) -> Self {
+        Self::new(self.f.clone())
+    }
+}
+
+impl<F, Fut, Req, Res, Err> Service<Req> for FnServiceFactory<F, Fut, Req, Res, Err, ()>
+where
+    F: Fn(Req) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    type Response = Res;
+    type Error = Err;
+    type Future = Fut;
+
+    crate::always_ready!();
+
+    fn call(&self, req: Req) -> Self::Future {
+        (self.f)(req)
+    }
+}
+
+impl<F, Fut, Req, Res, Err, Cfg> ServiceFactory<Req>
+    for FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
+where
+    F: Fn(Req) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    type Response = Res;
+    type Error = Err;
+
+    type Config = Cfg;
+    type Service = FnService<F, Fut, Req, Res, Err>;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: Cfg) -> Self::Future {
+        ok(FnService::new(self.f.clone()))
+    }
+}
+
+impl<F, Fut, Req, Res, Err, Cfg>
+    IntoServiceFactory<FnServiceFactory<F, Fut, Req, Res, Err, Cfg>, Req> for F
+where
+    F: Fn(Req) -> Fut + Clone,
+    Fut: Future<Output = Result<Res, Err>>,
+{
+    fn into_factory(self) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg> {
+        FnServiceFactory::new(self)
+    }
+}
+
+/// Convert `Fn(&Config) -> Future<Service>` fn to NewService
+pub struct FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
+where
+    F: Fn(Cfg) -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    f: F,
+    _t: PhantomData<fn(Cfg, Req) -> (Fut, Srv, Err)>,
+}
+
+impl<F, Fut, Cfg, Srv, Req, Err> FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
+where
+    F: Fn(Cfg) -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    fn new(f: F) -> Self {
+        FnServiceConfig { f, _t: PhantomData }
+    }
+}
+
+impl<F, Fut, Cfg, Srv, Req, Err> Clone for FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
+where
+    F: Fn(Cfg) -> Fut + Clone,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    fn clone(&self) -> Self {
+        FnServiceConfig {
+            f: self.f.clone(),
+            _t: PhantomData,
+        }
+    }
+}
+
+impl<F, Fut, Cfg, Srv, Req, Err> ServiceFactory<Req> for FnServiceConfig<F, Fut, Cfg, Srv, Req, Err>
+where
+    F: Fn(Cfg) -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    type Response = Srv::Response;
+    type Error = Srv::Error;
+
+    type Config = Cfg;
+    type Service = Srv;
+    type InitError = Err;
+    type Future = Fut;
+
+    fn new_service(&self, cfg: Cfg) -> Self::Future {
+        (self.f)(cfg)
+    }
+}
+
+/// Converter for `Fn() -> Future<Service>` fn
+pub struct FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
+where
+    F: Fn() -> Fut,
+    Srv: Service<Req>,
+    Fut: Future<Output = Result<Srv, Err>>,
+{
+    f: F,
+    _t: PhantomData<fn(Cfg, Req)>,
+}
+
+impl<F, Cfg, Srv, Req, Fut, Err> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
+where
+    F: Fn() -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    fn new(f: F) -> Self {
+        Self { f, _t: PhantomData }
+    }
+}
+
+impl<F, Cfg, Srv, Req, Fut, Err> ServiceFactory<Req>
+    for FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
+where
+    F: Fn() -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    type Response = Srv::Response;
+    type Error = Srv::Error;
+    type Config = Cfg;
+    type Service = Srv;
+    type InitError = Err;
+    type Future = Fut;
+
+    fn new_service(&self, _: Cfg) -> Self::Future {
+        (self.f)()
+    }
+}
+
+impl<F, Cfg, Srv, Req, Fut, Err> Clone for FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>
+where
+    F: Fn() -> Fut + Clone,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    fn clone(&self) -> Self {
+        Self::new(self.f.clone())
+    }
+}
+
+impl<F, Cfg, Srv, Req, Fut, Err>
+    IntoServiceFactory<FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err>, Req> for F
+where
+    F: Fn() -> Fut,
+    Fut: Future<Output = Result<Srv, Err>>,
+    Srv: Service<Req>,
+{
+    fn into_factory(self) -> FnServiceNoConfig<F, Cfg, Srv, Req, Fut, Err> {
+        FnServiceNoConfig::new(self)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use core::task::Poll;
+
+    use futures_util::future::lazy;
+
+    use super::*;
+
+    #[actix_rt::test]
+    async fn test_fn_service() {
+        let new_srv = fn_service(|()| ok::<_, ()>("srv"));
+
+        let srv = new_srv.new_service(()).await.unwrap();
+        let res = srv.call(()).await;
+        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), "srv");
+    }
+
+    #[actix_rt::test]
+    async fn test_fn_service_service() {
+        let srv = fn_service(|()| ok::<_, ()>("srv"));
+
+        let res = srv.call(()).await;
+        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), "srv");
+    }
+
+    #[actix_rt::test]
+    async fn test_fn_service_with_config() {
+        let new_srv = fn_factory_with_config(|cfg: usize| {
+            ok::<_, ()>(fn_service(move |()| ok::<_, ()>(("srv", cfg))))
+        });
+
+        let srv = new_srv.new_service(1).await.unwrap();
+        let res = srv.call(()).await;
+        assert_eq!(lazy(|cx| srv.poll_ready(cx)).await, Poll::Ready(Ok(())));
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv", 1));
+    }
+
+    #[actix_rt::test]
+    async fn test_auto_impl_send() {
+        use alloc::rc::Rc;
+
+        use crate::{map_config, ServiceExt, ServiceFactoryExt};
+
+        let srv_1 = fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8)));
+
+        let fac_1 = fn_factory_with_config(|_: Rc<u8>| {
+            ok::<_, Rc<u8>>(fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8))))
+        });
+
+        let fac_2 =
+            fn_factory(|| ok::<_, Rc<u8>>(fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8)))));
+
+        fn is_send<T: Send + Sync + Clone>(_: &T) {}
+
+        is_send(&fac_1);
+        is_send(&map_config(fac_1.clone(), |_: Rc<u8>| Rc::new(0u8)));
+        is_send(&fac_1.clone().map_err(|_| Rc::new(0u8)));
+        is_send(&fac_1.clone().map(|_| Rc::new(0u8)));
+        is_send(&fac_1.clone().map_init_err(|_| Rc::new(0u8)));
+        // `and_then` is always !Send
+        // is_send(&fac_1.clone().and_then(fac_1.clone()));
+        is_send(&fac_1.new_service(Rc::new(0u8)).await.unwrap());
+
+        is_send(&fac_2);
+        is_send(&fac_2.new_service(Rc::new(0u8)).await.unwrap());
+
+        is_send(&srv_1);
+        is_send(&ServiceExt::map(srv_1.clone(), |_| Rc::new(0u8)));
+        is_send(&ServiceExt::map_err(srv_1.clone(), |_| Rc::new(0u8)));
+        // `and_then` is always !Send
+        // is_send(&ServiceExt::and_then(srv_1.clone(), srv_1.clone()));
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/lib.rs.html b/src/actix_service/lib.rs.html new file mode 100644 index 00000000..39ae0d83 --- /dev/null +++ b/src/actix_service/lib.rs.html @@ -0,0 +1,651 @@ +lib.rs - source

actix_service/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
//! See [`Service`] docs for information on this crate's foundational trait.
+
+#![no_std]
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+#![allow(clippy::type_complexity)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
+extern crate alloc;
+
+use alloc::{boxed::Box, rc::Rc, sync::Arc};
+use core::{
+    cell::RefCell,
+    future::Future,
+    task::{self, Context, Poll},
+};
+
+mod and_then;
+mod apply;
+mod apply_cfg;
+pub mod boxed;
+mod ext;
+mod fn_service;
+mod macros;
+mod map;
+mod map_config;
+mod map_err;
+mod map_init_err;
+mod pipeline;
+mod ready;
+mod then;
+mod transform;
+mod transform_err;
+
+#[allow(unused_imports)]
+use self::ready::{err, ok, ready, Ready};
+pub use self::{
+    apply::{apply_fn, apply_fn_factory},
+    apply_cfg::{apply_cfg, apply_cfg_factory},
+    ext::{ServiceExt, ServiceFactoryExt, TransformExt},
+    fn_service::{fn_factory, fn_factory_with_config, fn_service},
+    map_config::{map_config, unit_config},
+    transform::{apply, ApplyTransform, Transform},
+};
+
+/// An asynchronous operation from `Request` to a `Response`.
+///
+/// The `Service` trait models a request/response interaction, receiving requests and returning
+/// replies. You can think about a service as a function with one argument that returns some result
+/// asynchronously. Conceptually, the operation looks like this:
+///
+/// ```ignore
+/// async fn(Request) -> Result<Response, Err>
+/// ```
+///
+/// The `Service` trait just generalizes this form. Requests are defined as a generic type parameter
+/// and responses and other details are defined as associated types on the trait impl. Notice that
+/// this design means that services can receive many request types and converge them to a single
+/// response type.
+///
+/// Services can also have mutable state that influence computation by using a `Cell`, `RefCell`
+/// or `Mutex`. Services intentionally do not take `&mut self` to reduce overhead in the
+/// common cases.
+///
+/// `Service` provides a symmetric and uniform API; the same abstractions can be used to represent
+/// both clients and servers. Services describe only _transformation_ operations which encourage
+/// simple API surfaces. This leads to simpler design of each service, improves test-ability and
+/// makes composition easier.
+///
+/// ```ignore
+/// struct MyService;
+///
+/// impl Service<u8> for MyService {
+///      type Response = u64;
+///      type Error = MyError;
+///      type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
+///
+///      fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { ... }
+///
+///      fn call(&self, req: u8) -> Self::Future { ... }
+/// }
+/// ```
+///
+/// Sometimes it is not necessary to implement the Service trait. For example, the above service
+/// could be rewritten as a simple function and passed to [`fn_service`](fn_service()).
+///
+/// ```ignore
+/// async fn my_service(req: u8) -> Result<u64, MyError>;
+///
+/// let svc = fn_service(my_service)
+/// svc.call(123)
+/// ```
+pub trait Service<Req> {
+    /// Responses given by the service.
+    type Response;
+
+    /// Errors produced by the service when polling readiness or executing call.
+    type Error;
+
+    /// The future response value.
+    type Future: Future<Output = Result<Self::Response, Self::Error>>;
+
+    /// Returns `Ready` when the service is able to process requests.
+    ///
+    /// If the service is at capacity, then `Pending` is returned and the task is notified when the
+    /// service becomes ready again. This function is expected to be called while on a task.
+    ///
+    /// This is a best effort implementation. False positives are permitted. It is permitted for
+    /// the service to return `Ready` from a `poll_ready` call and the next invocation of `call`
+    /// results in an error.
+    ///
+    /// # Notes
+    /// 1. `poll_ready` might be called on a different task to `call`.
+    /// 1. In cases of chained services, `.poll_ready()` is called for all services at once.
+    fn poll_ready(&self, ctx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
+
+    /// Process the request and return the response asynchronously.
+    ///
+    /// This function is expected to be callable off-task. As such, implementations of `call` should
+    /// take care to not call `poll_ready`. If the service is at capacity and the request is unable
+    /// to be handled, the returned `Future` should resolve to an error.
+    ///
+    /// Invoking `call` without first invoking `poll_ready` is permitted. Implementations must be
+    /// resilient to this fact.
+    fn call(&self, req: Req) -> Self::Future;
+}
+
+/// Factory for creating `Service`s.
+///
+/// This is useful for cases where new `Service`s must be produced. One case is a TCP
+/// server listener: a listener accepts new connections, constructs a new `Service` for each using
+/// the `ServiceFactory` trait, and uses the new `Service` to process inbound requests on that new
+/// connection.
+///
+/// `Config` is a service factory configuration type.
+///
+/// Simple factories may be able to use [`fn_factory`] or [`fn_factory_with_config`] to
+/// reduce boilerplate.
+pub trait ServiceFactory<Req> {
+    /// Responses given by the created services.
+    type Response;
+
+    /// Errors produced by the created services.
+    type Error;
+
+    /// Service factory configuration.
+    type Config;
+
+    /// The kind of `Service` created by this factory.
+    type Service: Service<Req, Response = Self::Response, Error = Self::Error>;
+
+    /// Errors potentially raised while building a service.
+    type InitError;
+
+    /// The future of the `Service` instance.g
+    type Future: Future<Output = Result<Self::Service, Self::InitError>>;
+
+    /// Create and return a new service asynchronously.
+    fn new_service(&self, cfg: Self::Config) -> Self::Future;
+}
+
+// TODO: remove implement on mut reference.
+impl<'a, S, Req> Service<Req> for &'a mut S
+where
+    S: Service<Req> + 'a,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = S::Future;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        (**self).poll_ready(ctx)
+    }
+
+    fn call(&self, request: Req) -> S::Future {
+        (**self).call(request)
+    }
+}
+
+impl<'a, S, Req> Service<Req> for &'a S
+where
+    S: Service<Req> + 'a,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = S::Future;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        (**self).poll_ready(ctx)
+    }
+
+    fn call(&self, request: Req) -> S::Future {
+        (**self).call(request)
+    }
+}
+
+impl<S, Req> Service<Req> for Box<S>
+where
+    S: Service<Req> + ?Sized,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = S::Future;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), S::Error>> {
+        (**self).poll_ready(ctx)
+    }
+
+    fn call(&self, request: Req) -> S::Future {
+        (**self).call(request)
+    }
+}
+
+impl<S, Req> Service<Req> for Rc<S>
+where
+    S: Service<Req> + ?Sized,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = S::Future;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        (**self).poll_ready(ctx)
+    }
+
+    fn call(&self, request: Req) -> S::Future {
+        (**self).call(request)
+    }
+}
+
+/// This impl is deprecated since v2 because the `Service` trait now receives shared reference.
+impl<S, Req> Service<Req> for RefCell<S>
+where
+    S: Service<Req>,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = S::Future;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        self.borrow().poll_ready(ctx)
+    }
+
+    fn call(&self, request: Req) -> S::Future {
+        self.borrow().call(request)
+    }
+}
+
+impl<S, Req> ServiceFactory<Req> for Rc<S>
+where
+    S: ServiceFactory<Req>,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Config = S::Config;
+    type Service = S::Service;
+    type InitError = S::InitError;
+    type Future = S::Future;
+
+    fn new_service(&self, cfg: S::Config) -> S::Future {
+        self.as_ref().new_service(cfg)
+    }
+}
+
+impl<S, Req> ServiceFactory<Req> for Arc<S>
+where
+    S: ServiceFactory<Req>,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Config = S::Config;
+    type Service = S::Service;
+    type InitError = S::InitError;
+    type Future = S::Future;
+
+    fn new_service(&self, cfg: S::Config) -> S::Future {
+        self.as_ref().new_service(cfg)
+    }
+}
+
+/// Trait for types that can be converted to a `Service`
+pub trait IntoService<S, Req>
+where
+    S: Service<Req>,
+{
+    /// Convert to a `Service`
+    fn into_service(self) -> S;
+}
+
+/// Trait for types that can be converted to a `ServiceFactory`
+pub trait IntoServiceFactory<SF, Req>
+where
+    SF: ServiceFactory<Req>,
+{
+    /// Convert `Self` to a `ServiceFactory`
+    fn into_factory(self) -> SF;
+}
+
+impl<S, Req> IntoService<S, Req> for S
+where
+    S: Service<Req>,
+{
+    fn into_service(self) -> S {
+        self
+    }
+}
+
+impl<SF, Req> IntoServiceFactory<SF, Req> for SF
+where
+    SF: ServiceFactory<Req>,
+{
+    fn into_factory(self) -> SF {
+        self
+    }
+}
+
+/// Convert object of type `U` to a service `S`
+pub fn into_service<I, S, Req>(tp: I) -> S
+where
+    I: IntoService<S, Req>,
+    S: Service<Req>,
+{
+    tp.into_service()
+}
+
\ No newline at end of file diff --git a/src/actix_service/macros.rs.html b/src/actix_service/macros.rs.html new file mode 100644 index 00000000..c90bcec7 --- /dev/null +++ b/src/actix_service/macros.rs.html @@ -0,0 +1,375 @@ +macros.rs - source

actix_service/
macros.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
/// An implementation of [`poll_ready`]() that always signals readiness.
+///
+/// This should only be used for basic leaf services that have no concept of un-readiness.
+/// For wrapper or other service types, use [`forward_ready!`] for simple cases or write a bespoke
+/// `poll_ready` implementation.
+///
+/// [`poll_ready`]: crate::Service::poll_ready
+///
+/// # Examples
+/// ```no_run
+/// use actix_service::Service;
+/// use futures_util::future::{ready, Ready};
+///
+/// struct IdentityService;
+///
+/// impl Service<u32> for IdentityService {
+///     type Response = u32;
+///     type Error = ();
+///     type Future = Ready<Result<Self::Response, Self::Error>>;
+///
+///     actix_service::always_ready!();
+///
+///     fn call(&self, req: u32) -> Self::Future {
+///         ready(Ok(req))
+///     }
+/// }
+/// ```
+///
+/// [`forward_ready!`]: crate::forward_ready
+#[macro_export]
+macro_rules! always_ready {
+    () => {
+        #[inline]
+        fn poll_ready(
+            &self,
+            _: &mut ::core::task::Context<'_>,
+        ) -> ::core::task::Poll<Result<(), Self::Error>> {
+            ::core::task::Poll::Ready(Ok(()))
+        }
+    };
+}
+
+/// An implementation of [`poll_ready`] that forwards readiness checks to a
+/// named struct field.
+///
+/// Tuple structs are not supported.
+///
+/// [`poll_ready`]: crate::Service::poll_ready
+///
+/// # Examples
+/// ```no_run
+/// use actix_service::Service;
+/// use futures_util::future::{ready, Ready};
+///
+/// struct WrapperService<S> {
+///     inner: S,
+/// }
+///
+/// impl<S> Service<()> for WrapperService<S>
+/// where
+///     S: Service<()>,
+/// {
+///     type Response = S::Response;
+///     type Error = S::Error;
+///     type Future = S::Future;
+///
+///     actix_service::forward_ready!(inner);
+///
+///     fn call(&self, req: ()) -> Self::Future {
+///         self.inner.call(req)
+///     }
+/// }
+/// ```
+#[macro_export]
+macro_rules! forward_ready {
+    ($field:ident) => {
+        #[inline]
+        fn poll_ready(
+            &self,
+            cx: &mut ::core::task::Context<'_>,
+        ) -> ::core::task::Poll<Result<(), Self::Error>> {
+            self.$field
+                .poll_ready(cx)
+                .map_err(::core::convert::Into::into)
+        }
+    };
+}
+
+#[cfg(test)]
+mod tests {
+    use core::{
+        cell::Cell,
+        convert::Infallible,
+        task::{self, Context, Poll},
+    };
+
+    use futures_util::{
+        future::{ready, Ready},
+        task::noop_waker,
+    };
+
+    use crate::Service;
+
+    struct IdentityService;
+
+    impl Service<u32> for IdentityService {
+        type Response = u32;
+        type Error = Infallible;
+        type Future = Ready<Result<Self::Response, Self::Error>>;
+
+        always_ready!();
+
+        fn call(&self, req: u32) -> Self::Future {
+            ready(Ok(req))
+        }
+    }
+
+    struct CountdownService(Cell<u32>);
+
+    impl Service<()> for CountdownService {
+        type Response = ();
+        type Error = Infallible;
+        type Future = Ready<Result<Self::Response, Self::Error>>;
+
+        fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+            let count = self.0.get();
+
+            if count == 0 {
+                Poll::Ready(Ok(()))
+            } else {
+                self.0.set(count - 1);
+                cx.waker().wake_by_ref();
+                Poll::Pending
+            }
+        }
+
+        fn call(&self, _: ()) -> Self::Future {
+            ready(Ok(()))
+        }
+    }
+
+    struct WrapperService<S> {
+        inner: S,
+    }
+
+    impl<S> Service<()> for WrapperService<S>
+    where
+        S: Service<()>,
+    {
+        type Response = S::Response;
+        type Error = S::Error;
+        type Future = S::Future;
+
+        forward_ready!(inner);
+
+        fn call(&self, _: ()) -> Self::Future {
+            self.inner.call(())
+        }
+    }
+
+    #[test]
+    fn test_always_ready_macro() {
+        let waker = noop_waker();
+        let mut cx = task::Context::from_waker(&waker);
+
+        let svc = IdentityService;
+
+        assert!(svc.poll_ready(&mut cx).is_ready());
+        assert!(svc.poll_ready(&mut cx).is_ready());
+        assert!(svc.poll_ready(&mut cx).is_ready());
+    }
+
+    #[test]
+    fn test_forward_ready_macro() {
+        let waker = noop_waker();
+        let mut cx = task::Context::from_waker(&waker);
+
+        let svc = WrapperService {
+            inner: CountdownService(Cell::new(3)),
+        };
+
+        assert!(svc.poll_ready(&mut cx).is_pending());
+        assert!(svc.poll_ready(&mut cx).is_pending());
+        assert!(svc.poll_ready(&mut cx).is_pending());
+        assert!(svc.poll_ready(&mut cx).is_ready());
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/map.rs.html b/src/actix_service/map.rs.html new file mode 100644 index 00000000..6641015e --- /dev/null +++ b/src/actix_service/map.rs.html @@ -0,0 +1,489 @@ +map.rs - source

actix_service/
map.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use pin_project_lite::pin_project;
+
+use super::{Service, ServiceFactory};
+
+/// Service for the `map` combinator, changing the type of a service's response.
+///
+/// This is created by the `ServiceExt::map` method.
+pub struct Map<A, F, Req, Res> {
+    service: A,
+    f: F,
+    _t: PhantomData<fn(Req) -> Res>,
+}
+
+impl<A, F, Req, Res> Map<A, F, Req, Res> {
+    /// Create new `Map` combinator
+    pub(crate) fn new(service: A, f: F) -> Self
+    where
+        A: Service<Req>,
+        F: FnMut(A::Response) -> Res,
+    {
+        Self {
+            service,
+            f,
+            _t: PhantomData,
+        }
+    }
+}
+
+impl<A, F, Req, Res> Clone for Map<A, F, Req, Res>
+where
+    A: Clone,
+    F: Clone,
+{
+    fn clone(&self) -> Self {
+        Map {
+            service: self.service.clone(),
+            f: self.f.clone(),
+            _t: PhantomData,
+        }
+    }
+}
+
+impl<A, F, Req, Res> Service<Req> for Map<A, F, Req, Res>
+where
+    A: Service<Req>,
+    F: FnMut(A::Response) -> Res + Clone,
+{
+    type Response = Res;
+    type Error = A::Error;
+    type Future = MapFuture<A, F, Req, Res>;
+
+    crate::forward_ready!(service);
+
+    fn call(&self, req: Req) -> Self::Future {
+        MapFuture::new(self.service.call(req), self.f.clone())
+    }
+}
+
+pin_project! {
+    pub struct MapFuture<A, F, Req, Res>
+    where
+        A: Service<Req>,
+        F: FnMut(A::Response) -> Res,
+    {
+        f: F,
+        #[pin]
+        fut: A::Future,
+    }
+}
+
+impl<A, F, Req, Res> MapFuture<A, F, Req, Res>
+where
+    A: Service<Req>,
+    F: FnMut(A::Response) -> Res,
+{
+    fn new(fut: A::Future, f: F) -> Self {
+        MapFuture { f, fut }
+    }
+}
+
+impl<A, F, Req, Res> Future for MapFuture<A, F, Req, Res>
+where
+    A: Service<Req>,
+    F: FnMut(A::Response) -> Res,
+{
+    type Output = Result<Res, A::Error>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+
+        match this.fut.poll(cx) {
+            Poll::Ready(Ok(resp)) => Poll::Ready(Ok((this.f)(resp))),
+            Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
+            Poll::Pending => Poll::Pending,
+        }
+    }
+}
+
+/// `MapNewService` new service combinator
+pub struct MapServiceFactory<A, F, Req, Res> {
+    a: A,
+    f: F,
+    r: PhantomData<fn(Req) -> Res>,
+}
+
+impl<A, F, Req, Res> MapServiceFactory<A, F, Req, Res> {
+    /// Create new `Map` new service instance
+    pub(crate) fn new(a: A, f: F) -> Self
+    where
+        A: ServiceFactory<Req>,
+        F: FnMut(A::Response) -> Res,
+    {
+        Self {
+            a,
+            f,
+            r: PhantomData,
+        }
+    }
+}
+
+impl<A, F, Req, Res> Clone for MapServiceFactory<A, F, Req, Res>
+where
+    A: Clone,
+    F: Clone,
+{
+    fn clone(&self) -> Self {
+        Self {
+            a: self.a.clone(),
+            f: self.f.clone(),
+            r: PhantomData,
+        }
+    }
+}
+
+impl<A, F, Req, Res> ServiceFactory<Req> for MapServiceFactory<A, F, Req, Res>
+where
+    A: ServiceFactory<Req>,
+    F: FnMut(A::Response) -> Res + Clone,
+{
+    type Response = Res;
+    type Error = A::Error;
+
+    type Config = A::Config;
+    type Service = Map<A::Service, F, Req, Res>;
+    type InitError = A::InitError;
+    type Future = MapServiceFuture<A, F, Req, Res>;
+
+    fn new_service(&self, cfg: A::Config) -> Self::Future {
+        MapServiceFuture::new(self.a.new_service(cfg), self.f.clone())
+    }
+}
+
+pin_project! {
+    pub struct MapServiceFuture<A, F, Req, Res>
+    where
+        A: ServiceFactory<Req>,
+        F: FnMut(A::Response) -> Res,
+    {
+        #[pin]
+        fut: A::Future,
+        f: Option<F>,
+    }
+}
+
+impl<A, F, Req, Res> MapServiceFuture<A, F, Req, Res>
+where
+    A: ServiceFactory<Req>,
+    F: FnMut(A::Response) -> Res,
+{
+    fn new(fut: A::Future, f: F) -> Self {
+        MapServiceFuture { f: Some(f), fut }
+    }
+}
+
+impl<A, F, Req, Res> Future for MapServiceFuture<A, F, Req, Res>
+where
+    A: ServiceFactory<Req>,
+    F: FnMut(A::Response) -> Res,
+{
+    type Output = Result<Map<A::Service, F, Req, Res>, A::InitError>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+
+        if let Poll::Ready(svc) = this.fut.poll(cx)? {
+            Poll::Ready(Ok(Map::new(svc, this.f.take().unwrap())))
+        } else {
+            Poll::Pending
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use futures_util::future::lazy;
+
+    use super::*;
+    use crate::{ok, IntoServiceFactory, Ready, ServiceExt, ServiceFactoryExt};
+
+    struct Srv;
+
+    impl Service<()> for Srv {
+        type Response = ();
+        type Error = ();
+        type Future = Ready<Result<(), ()>>;
+
+        crate::always_ready!();
+
+        fn call(&self, _: ()) -> Self::Future {
+            ok(())
+        }
+    }
+
+    #[actix_rt::test]
+    async fn test_poll_ready() {
+        let srv = Srv.map(|_| "ok");
+        let res = lazy(|cx| srv.poll_ready(cx)).await;
+        assert_eq!(res, Poll::Ready(Ok(())));
+    }
+
+    #[actix_rt::test]
+    async fn test_call() {
+        let srv = Srv.map(|_| "ok");
+        let res = srv.call(()).await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), "ok");
+    }
+
+    #[actix_rt::test]
+    async fn test_new_service() {
+        let new_srv = (|| ok::<_, ()>(Srv)).into_factory().map(|_| "ok");
+        let srv = new_srv.new_service(&()).await.unwrap();
+        let res = srv.call(()).await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("ok"));
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/map_config.rs.html b/src/actix_service/map_config.rs.html new file mode 100644 index 00000000..20f4dd10 --- /dev/null +++ b/src/actix_service/map_config.rs.html @@ -0,0 +1,257 @@ +map_config.rs - source

actix_service/
map_config.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
use core::marker::PhantomData;
+
+use super::{IntoServiceFactory, ServiceFactory};
+
+/// Adapt external config argument to a config for provided service factory
+///
+/// Note that this function consumes the receiving service factory and returns
+/// a wrapped version of it.
+pub fn map_config<I, SF, Req, F, Cfg>(factory: I, f: F) -> MapConfig<SF, Req, F, Cfg>
+where
+    I: IntoServiceFactory<SF, Req>,
+    SF: ServiceFactory<Req>,
+    F: Fn(Cfg) -> SF::Config,
+{
+    MapConfig::new(factory.into_factory(), f)
+}
+
+/// Replace config with unit.
+pub fn unit_config<I, SF, Cfg, Req>(factory: I) -> UnitConfig<SF, Cfg, Req>
+where
+    I: IntoServiceFactory<SF, Req>,
+    SF: ServiceFactory<Req, Config = ()>,
+{
+    UnitConfig::new(factory.into_factory())
+}
+
+/// `map_config()` adapter service factory
+pub struct MapConfig<SF, Req, F, Cfg> {
+    factory: SF,
+    cfg_mapper: F,
+    e: PhantomData<fn(Cfg, Req)>,
+}
+
+impl<SF, Req, F, Cfg> MapConfig<SF, Req, F, Cfg> {
+    /// Create new `MapConfig` combinator
+    pub(crate) fn new(factory: SF, cfg_mapper: F) -> Self
+    where
+        SF: ServiceFactory<Req>,
+        F: Fn(Cfg) -> SF::Config,
+    {
+        Self {
+            factory,
+            cfg_mapper,
+            e: PhantomData,
+        }
+    }
+}
+
+impl<SF, Req, F, Cfg> Clone for MapConfig<SF, Req, F, Cfg>
+where
+    SF: Clone,
+    F: Clone,
+{
+    fn clone(&self) -> Self {
+        Self {
+            factory: self.factory.clone(),
+            cfg_mapper: self.cfg_mapper.clone(),
+            e: PhantomData,
+        }
+    }
+}
+
+impl<SF, Req, F, Cfg> ServiceFactory<Req> for MapConfig<SF, Req, F, Cfg>
+where
+    SF: ServiceFactory<Req>,
+    F: Fn(Cfg) -> SF::Config,
+{
+    type Response = SF::Response;
+    type Error = SF::Error;
+
+    type Config = Cfg;
+    type Service = SF::Service;
+    type InitError = SF::InitError;
+    type Future = SF::Future;
+
+    fn new_service(&self, cfg: Self::Config) -> Self::Future {
+        let mapped_cfg = (self.cfg_mapper)(cfg);
+        self.factory.new_service(mapped_cfg)
+    }
+}
+
+/// `unit_config()` config combinator
+pub struct UnitConfig<SF, Cfg, Req> {
+    factory: SF,
+    _phantom: PhantomData<fn(Cfg, Req)>,
+}
+
+impl<SF, Cfg, Req> UnitConfig<SF, Cfg, Req>
+where
+    SF: ServiceFactory<Req, Config = ()>,
+{
+    /// Create new `UnitConfig` combinator
+    pub(crate) fn new(factory: SF) -> Self {
+        Self {
+            factory,
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<SF, Cfg, Req> Clone for UnitConfig<SF, Cfg, Req>
+where
+    SF: Clone,
+{
+    fn clone(&self) -> Self {
+        Self {
+            factory: self.factory.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<SF, Cfg, Req> ServiceFactory<Req> for UnitConfig<SF, Cfg, Req>
+where
+    SF: ServiceFactory<Req, Config = ()>,
+{
+    type Response = SF::Response;
+    type Error = SF::Error;
+
+    type Config = Cfg;
+    type Service = SF::Service;
+    type InitError = SF::InitError;
+    type Future = SF::Future;
+
+    fn new_service(&self, _: Cfg) -> Self::Future {
+        self.factory.new_service(())
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/map_err.rs.html b/src/actix_service/map_err.rs.html new file mode 100644 index 00000000..2972033f --- /dev/null +++ b/src/actix_service/map_err.rs.html @@ -0,0 +1,499 @@ +map_err.rs - source

actix_service/
map_err.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use pin_project_lite::pin_project;
+
+use super::{Service, ServiceFactory};
+
+/// Service for the `map_err` combinator, changing the type of a service's error.
+///
+/// This is created by the `ServiceExt::map_err` method.
+pub struct MapErr<S, Req, F, E> {
+    service: S,
+    mapper: F,
+    _t: PhantomData<fn(Req) -> E>,
+}
+
+impl<S, Req, F, E> MapErr<S, Req, F, E> {
+    /// Create new `MapErr` combinator
+    pub(crate) fn new(service: S, mapper: F) -> Self
+    where
+        S: Service<Req>,
+        F: Fn(S::Error) -> E,
+    {
+        Self {
+            service,
+            mapper,
+            _t: PhantomData,
+        }
+    }
+}
+
+impl<S, Req, F, E> Clone for MapErr<S, Req, F, E>
+where
+    S: Clone,
+    F: Clone,
+{
+    fn clone(&self) -> Self {
+        MapErr {
+            service: self.service.clone(),
+            mapper: self.mapper.clone(),
+            _t: PhantomData,
+        }
+    }
+}
+
+impl<A, Req, F, E> Service<Req> for MapErr<A, Req, F, E>
+where
+    A: Service<Req>,
+    F: Fn(A::Error) -> E + Clone,
+{
+    type Response = A::Response;
+    type Error = E;
+    type Future = MapErrFuture<A, Req, F, E>;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        self.service.poll_ready(ctx).map_err(&self.mapper)
+    }
+
+    fn call(&self, req: Req) -> Self::Future {
+        MapErrFuture::new(self.service.call(req), self.mapper.clone())
+    }
+}
+
+pin_project! {
+    pub struct MapErrFuture<A, Req, F, E>
+    where
+        A: Service<Req>,
+        F: Fn(A::Error) -> E,
+    {
+        f: F,
+        #[pin]
+        fut: A::Future,
+    }
+}
+
+impl<A, Req, F, E> MapErrFuture<A, Req, F, E>
+where
+    A: Service<Req>,
+    F: Fn(A::Error) -> E,
+{
+    fn new(fut: A::Future, f: F) -> Self {
+        MapErrFuture { f, fut }
+    }
+}
+
+impl<A, Req, F, E> Future for MapErrFuture<A, Req, F, E>
+where
+    A: Service<Req>,
+    F: Fn(A::Error) -> E,
+{
+    type Output = Result<A::Response, E>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+        this.fut.poll(cx).map_err(this.f)
+    }
+}
+
+/// Factory for the `map_err` combinator, changing the type of a new
+/// service's error.
+///
+/// This is created by the `NewServiceExt::map_err` method.
+pub struct MapErrServiceFactory<SF, Req, F, E>
+where
+    SF: ServiceFactory<Req>,
+    F: Fn(SF::Error) -> E + Clone,
+{
+    a: SF,
+    f: F,
+    e: PhantomData<fn(Req) -> E>,
+}
+
+impl<SF, Req, F, E> MapErrServiceFactory<SF, Req, F, E>
+where
+    SF: ServiceFactory<Req>,
+    F: Fn(SF::Error) -> E + Clone,
+{
+    /// Create new `MapErr` new service instance
+    pub(crate) fn new(a: SF, f: F) -> Self {
+        Self {
+            a,
+            f,
+            e: PhantomData,
+        }
+    }
+}
+
+impl<SF, Req, F, E> Clone for MapErrServiceFactory<SF, Req, F, E>
+where
+    SF: ServiceFactory<Req> + Clone,
+    F: Fn(SF::Error) -> E + Clone,
+{
+    fn clone(&self) -> Self {
+        Self {
+            a: self.a.clone(),
+            f: self.f.clone(),
+            e: PhantomData,
+        }
+    }
+}
+
+impl<SF, Req, F, E> ServiceFactory<Req> for MapErrServiceFactory<SF, Req, F, E>
+where
+    SF: ServiceFactory<Req>,
+    F: Fn(SF::Error) -> E + Clone,
+{
+    type Response = SF::Response;
+    type Error = E;
+
+    type Config = SF::Config;
+    type Service = MapErr<SF::Service, Req, F, E>;
+    type InitError = SF::InitError;
+    type Future = MapErrServiceFuture<SF, Req, F, E>;
+
+    fn new_service(&self, cfg: SF::Config) -> Self::Future {
+        MapErrServiceFuture::new(self.a.new_service(cfg), self.f.clone())
+    }
+}
+
+pin_project! {
+    pub struct MapErrServiceFuture<SF, Req, F, E>
+    where
+        SF: ServiceFactory<Req>,
+        F: Fn(SF::Error) -> E,
+    {
+        #[pin]
+        fut: SF::Future,
+        mapper: F,
+    }
+}
+
+impl<SF, Req, F, E> MapErrServiceFuture<SF, Req, F, E>
+where
+    SF: ServiceFactory<Req>,
+    F: Fn(SF::Error) -> E,
+{
+    fn new(fut: SF::Future, mapper: F) -> Self {
+        MapErrServiceFuture { fut, mapper }
+    }
+}
+
+impl<SF, Req, F, E> Future for MapErrServiceFuture<SF, Req, F, E>
+where
+    SF: ServiceFactory<Req>,
+    F: Fn(SF::Error) -> E + Clone,
+{
+    type Output = Result<MapErr<SF::Service, Req, F, E>, SF::InitError>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+        if let Poll::Ready(svc) = this.fut.poll(cx)? {
+            Poll::Ready(Ok(MapErr::new(svc, this.mapper.clone())))
+        } else {
+            Poll::Pending
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use futures_util::future::lazy;
+
+    use super::*;
+    use crate::{err, ok, IntoServiceFactory, Ready, ServiceExt, ServiceFactoryExt};
+
+    struct Srv;
+
+    impl Service<()> for Srv {
+        type Response = ();
+        type Error = ();
+        type Future = Ready<Result<(), ()>>;
+
+        fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+            Poll::Ready(Err(()))
+        }
+
+        fn call(&self, _: ()) -> Self::Future {
+            err(())
+        }
+    }
+
+    #[actix_rt::test]
+    async fn test_poll_ready() {
+        let srv = Srv.map_err(|_| "error");
+        let res = lazy(|cx| srv.poll_ready(cx)).await;
+        assert_eq!(res, Poll::Ready(Err("error")));
+    }
+
+    #[actix_rt::test]
+    async fn test_call() {
+        let srv = Srv.map_err(|_| "error");
+        let res = srv.call(()).await;
+        assert!(res.is_err());
+        assert_eq!(res.err().unwrap(), "error");
+    }
+
+    #[actix_rt::test]
+    async fn test_new_service() {
+        let new_srv = (|| ok::<_, ()>(Srv)).into_factory().map_err(|_| "error");
+        let srv = new_srv.new_service(&()).await.unwrap();
+        let res = srv.call(()).await;
+        assert!(res.is_err());
+        assert_eq!(res.err().unwrap(), "error");
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/map_init_err.rs.html b/src/actix_service/map_init_err.rs.html new file mode 100644 index 00000000..0faca6ab --- /dev/null +++ b/src/actix_service/map_init_err.rs.html @@ -0,0 +1,199 @@ +map_init_err.rs - source

actix_service/
map_init_err.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use pin_project_lite::pin_project;
+
+use super::ServiceFactory;
+
+/// `MapInitErr` service combinator
+pub struct MapInitErr<A, F, Req, Err> {
+    a: A,
+    f: F,
+    e: PhantomData<fn(Req) -> Err>,
+}
+
+impl<A, F, Req, Err> MapInitErr<A, F, Req, Err>
+where
+    A: ServiceFactory<Req>,
+    F: Fn(A::InitError) -> Err,
+{
+    /// Create new `MapInitErr` combinator
+    pub(crate) fn new(a: A, f: F) -> Self {
+        Self {
+            a,
+            f,
+            e: PhantomData,
+        }
+    }
+}
+
+impl<A, F, Req, E> Clone for MapInitErr<A, F, Req, E>
+where
+    A: Clone,
+    F: Clone,
+{
+    fn clone(&self) -> Self {
+        Self {
+            a: self.a.clone(),
+            f: self.f.clone(),
+            e: PhantomData,
+        }
+    }
+}
+
+impl<A, F, Req, E> ServiceFactory<Req> for MapInitErr<A, F, Req, E>
+where
+    A: ServiceFactory<Req>,
+    F: Fn(A::InitError) -> E + Clone,
+{
+    type Response = A::Response;
+    type Error = A::Error;
+
+    type Config = A::Config;
+    type Service = A::Service;
+    type InitError = E;
+    type Future = MapInitErrFuture<A, F, Req, E>;
+
+    fn new_service(&self, cfg: A::Config) -> Self::Future {
+        MapInitErrFuture::new(self.a.new_service(cfg), self.f.clone())
+    }
+}
+
+pin_project! {
+    pub struct MapInitErrFuture<A, F, Req, E>
+    where
+        A: ServiceFactory<Req>,
+        F: Fn(A::InitError) -> E,
+    {
+        f: F,
+        #[pin]
+        fut: A::Future,
+    }
+}
+
+impl<A, F, Req, E> MapInitErrFuture<A, F, Req, E>
+where
+    A: ServiceFactory<Req>,
+    F: Fn(A::InitError) -> E,
+{
+    fn new(fut: A::Future, f: F) -> Self {
+        MapInitErrFuture { f, fut }
+    }
+}
+
+impl<A, F, Req, E> Future for MapInitErrFuture<A, F, Req, E>
+where
+    A: ServiceFactory<Req>,
+    F: Fn(A::InitError) -> E,
+{
+    type Output = Result<A::Service, E>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+        this.fut.poll(cx).map_err(this.f)
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/pipeline.rs.html b/src/actix_service/pipeline.rs.html new file mode 100644 index 00000000..0168c6b5 --- /dev/null +++ b/src/actix_service/pipeline.rs.html @@ -0,0 +1,617 @@ +pipeline.rs - source

actix_service/
pipeline.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
// TODO: see if pipeline is necessary
+#![allow(dead_code)]
+
+use core::{
+    marker::PhantomData,
+    task::{Context, Poll},
+};
+
+use crate::{
+    and_then::{AndThenService, AndThenServiceFactory},
+    map::{Map, MapServiceFactory},
+    map_err::{MapErr, MapErrServiceFactory},
+    map_init_err::MapInitErr,
+    then::{ThenService, ThenServiceFactory},
+    IntoService, IntoServiceFactory, Service, ServiceFactory,
+};
+
+/// Construct new pipeline with one service in pipeline chain.
+pub(crate) fn pipeline<I, S, Req>(service: I) -> Pipeline<S, Req>
+where
+    I: IntoService<S, Req>,
+    S: Service<Req>,
+{
+    Pipeline {
+        service: service.into_service(),
+        _phantom: PhantomData,
+    }
+}
+
+/// Construct new pipeline factory with one service factory.
+pub(crate) fn pipeline_factory<I, SF, Req>(factory: I) -> PipelineFactory<SF, Req>
+where
+    I: IntoServiceFactory<SF, Req>,
+    SF: ServiceFactory<Req>,
+{
+    PipelineFactory {
+        factory: factory.into_factory(),
+        _phantom: PhantomData,
+    }
+}
+
+/// Pipeline service - pipeline allows to compose multiple service into one service.
+pub(crate) struct Pipeline<S, Req> {
+    service: S,
+    _phantom: PhantomData<fn(Req)>,
+}
+
+impl<S, Req> Pipeline<S, Req>
+where
+    S: Service<Req>,
+{
+    /// Call another service after call to this one has resolved successfully.
+    ///
+    /// This function can be used to chain two services together and ensure that
+    /// the second service isn't called until call to the first service have
+    /// finished. Result of the call to the first service is used as an
+    /// input parameter for the second service's call.
+    ///
+    /// Note that this function consumes the receiving service and returns a
+    /// wrapped version of it.
+    pub fn and_then<I, S1>(
+        self,
+        service: I,
+    ) -> Pipeline<impl Service<Req, Response = S1::Response, Error = S::Error> + Clone, Req>
+    where
+        Self: Sized,
+        I: IntoService<S1, S::Response>,
+        S1: Service<S::Response, Error = S::Error>,
+    {
+        Pipeline {
+            service: AndThenService::new(self.service, service.into_service()),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Chain on a computation for when a call to the service finished,
+    /// passing the result of the call to the next service `U`.
+    ///
+    /// Note that this function consumes the receiving pipeline and returns a
+    /// wrapped version of it.
+    pub fn then<F, S1>(
+        self,
+        service: F,
+    ) -> Pipeline<impl Service<Req, Response = S1::Response, Error = S::Error> + Clone, Req>
+    where
+        Self: Sized,
+        F: IntoService<S1, Result<S::Response, S::Error>>,
+        S1: Service<Result<S::Response, S::Error>, Error = S::Error>,
+    {
+        Pipeline {
+            service: ThenService::new(self.service, service.into_service()),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Map this service's output to a different type, returning a new service
+    /// of the resulting type.
+    ///
+    /// This function is similar to the `Option::map` or `Iterator::map` where
+    /// it will change the type of the underlying service.
+    ///
+    /// Note that this function consumes the receiving service and returns a
+    /// wrapped version of it, similar to the existing `map` methods in the
+    /// standard library.
+    pub fn map<F, R>(self, f: F) -> Pipeline<Map<S, F, Req, R>, Req>
+    where
+        Self: Sized,
+        F: FnMut(S::Response) -> R,
+    {
+        Pipeline {
+            service: Map::new(self.service, f),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Map this service's error to a different error, returning a new service.
+    ///
+    /// This function is similar to the `Result::map_err` where it will change
+    /// the error type of the underlying service. This is useful for example to
+    /// ensure that services have the same error type.
+    ///
+    /// Note that this function consumes the receiving service and returns a
+    /// wrapped version of it.
+    pub fn map_err<F, E>(self, f: F) -> Pipeline<MapErr<S, Req, F, E>, Req>
+    where
+        Self: Sized,
+        F: Fn(S::Error) -> E,
+    {
+        Pipeline {
+            service: MapErr::new(self.service, f),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<T, Req> Clone for Pipeline<T, Req>
+where
+    T: Clone,
+{
+    fn clone(&self) -> Self {
+        Pipeline {
+            service: self.service.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<S: Service<Req>, Req> Service<Req> for Pipeline<S, Req> {
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = S::Future;
+
+    #[inline]
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), S::Error>> {
+        self.service.poll_ready(ctx)
+    }
+
+    #[inline]
+    fn call(&self, req: Req) -> Self::Future {
+        self.service.call(req)
+    }
+}
+
+/// Pipeline factory
+pub(crate) struct PipelineFactory<SF, Req> {
+    factory: SF,
+    _phantom: PhantomData<fn(Req)>,
+}
+
+impl<SF, Req> PipelineFactory<SF, Req>
+where
+    SF: ServiceFactory<Req>,
+{
+    /// Call another service after call to this one has resolved successfully.
+    pub fn and_then<I, SF1>(
+        self,
+        factory: I,
+    ) -> PipelineFactory<
+        impl ServiceFactory<
+                Req,
+                Response = SF1::Response,
+                Error = SF::Error,
+                Config = SF::Config,
+                InitError = SF::InitError,
+                Service = impl Service<Req, Response = SF1::Response, Error = SF::Error> + Clone,
+            > + Clone,
+        Req,
+    >
+    where
+        Self: Sized,
+        SF::Config: Clone,
+        I: IntoServiceFactory<SF1, SF::Response>,
+        SF1: ServiceFactory<
+            SF::Response,
+            Config = SF::Config,
+            Error = SF::Error,
+            InitError = SF::InitError,
+        >,
+    {
+        PipelineFactory {
+            factory: AndThenServiceFactory::new(self.factory, factory.into_factory()),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Create `NewService` to chain on a computation for when a call to the
+    /// service finished, passing the result of the call to the next
+    /// service `U`.
+    ///
+    /// Note that this function consumes the receiving pipeline and returns a
+    /// wrapped version of it.
+    pub fn then<I, SF1>(
+        self,
+        factory: I,
+    ) -> PipelineFactory<
+        impl ServiceFactory<
+                Req,
+                Response = SF1::Response,
+                Error = SF::Error,
+                Config = SF::Config,
+                InitError = SF::InitError,
+                Service = impl Service<Req, Response = SF1::Response, Error = SF::Error> + Clone,
+            > + Clone,
+        Req,
+    >
+    where
+        Self: Sized,
+        SF::Config: Clone,
+        I: IntoServiceFactory<SF1, Result<SF::Response, SF::Error>>,
+        SF1: ServiceFactory<
+            Result<SF::Response, SF::Error>,
+            Config = SF::Config,
+            Error = SF::Error,
+            InitError = SF::InitError,
+        >,
+    {
+        PipelineFactory {
+            factory: ThenServiceFactory::new(self.factory, factory.into_factory()),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Map this service's output to a different type, returning a new service
+    /// of the resulting type.
+    pub fn map<F, R>(self, f: F) -> PipelineFactory<MapServiceFactory<SF, F, Req, R>, Req>
+    where
+        Self: Sized,
+        F: FnMut(SF::Response) -> R + Clone,
+    {
+        PipelineFactory {
+            factory: MapServiceFactory::new(self.factory, f),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Map this service's error to a different error, returning a new service.
+    pub fn map_err<F, E>(self, f: F) -> PipelineFactory<MapErrServiceFactory<SF, Req, F, E>, Req>
+    where
+        Self: Sized,
+        F: Fn(SF::Error) -> E + Clone,
+    {
+        PipelineFactory {
+            factory: MapErrServiceFactory::new(self.factory, f),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Map this factory's init error to a different error, returning a new service.
+    pub fn map_init_err<F, E>(self, f: F) -> PipelineFactory<MapInitErr<SF, F, Req, E>, Req>
+    where
+        Self: Sized,
+        F: Fn(SF::InitError) -> E + Clone,
+    {
+        PipelineFactory {
+            factory: MapInitErr::new(self.factory, f),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<T, Req> Clone for PipelineFactory<T, Req>
+where
+    T: Clone,
+{
+    fn clone(&self) -> Self {
+        PipelineFactory {
+            factory: self.factory.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<SF, Req> ServiceFactory<Req> for PipelineFactory<SF, Req>
+where
+    SF: ServiceFactory<Req>,
+{
+    type Config = SF::Config;
+    type Response = SF::Response;
+    type Error = SF::Error;
+    type Service = SF::Service;
+    type InitError = SF::InitError;
+    type Future = SF::Future;
+
+    #[inline]
+    fn new_service(&self, cfg: SF::Config) -> Self::Future {
+        self.factory.new_service(cfg)
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/ready.rs.html b/src/actix_service/ready.rs.html new file mode 100644 index 00000000..8097bc1f --- /dev/null +++ b/src/actix_service/ready.rs.html @@ -0,0 +1,109 @@ +ready.rs - source

actix_service/
ready.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
//! When MSRV is 1.48, replace with `core::future::Ready` and `core::future::ready()`.
+
+use core::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+/// Future for the [`ready`](ready()) function.
+#[derive(Debug, Clone)]
+#[must_use = "futures do nothing unless you `.await` or poll them"]
+pub struct Ready<T> {
+    val: Option<T>,
+}
+
+impl<T> Ready<T> {
+    /// Unwraps the value from this immediately ready future.
+    #[inline]
+    pub fn into_inner(mut self) -> T {
+        self.val.take().unwrap()
+    }
+}
+
+impl<T> Unpin for Ready<T> {}
+
+impl<T> Future for Ready<T> {
+    type Output = T;
+
+    #[inline]
+    fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
+        let val = self.val.take().expect("Ready can not be polled twice.");
+        Poll::Ready(val)
+    }
+}
+
+/// Creates a future that is immediately ready with a value.
+#[allow(dead_code)]
+pub(crate) fn ready<T>(val: T) -> Ready<T> {
+    Ready { val: Some(val) }
+}
+
+/// Create a future that is immediately ready with a success value.
+#[allow(dead_code)]
+pub(crate) fn ok<T, E>(val: T) -> Ready<Result<T, E>> {
+    Ready { val: Some(Ok(val)) }
+}
+
+/// Create a future that is immediately ready with an error value.
+#[allow(dead_code)]
+pub(crate) fn err<T, E>(err: E) -> Ready<Result<T, E>> {
+    Ready {
+        val: Some(Err(err)),
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/then.rs.html b/src/actix_service/then.rs.html new file mode 100644 index 00000000..92dbd226 --- /dev/null +++ b/src/actix_service/then.rs.html @@ -0,0 +1,669 @@ +then.rs - source

actix_service/
then.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
use alloc::rc::Rc;
+use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use futures_core::ready;
+use pin_project_lite::pin_project;
+
+use super::{Service, ServiceFactory};
+
+/// Service for the `then` combinator, chaining a computation onto the end of
+/// another service.
+///
+/// This is created by the `Pipeline::then` method.
+pub(crate) struct ThenService<A, B, Req>(Rc<(A, B)>, PhantomData<Req>);
+
+impl<A, B, Req> ThenService<A, B, Req> {
+    /// Create new `.then()` combinator
+    pub(crate) fn new(a: A, b: B) -> ThenService<A, B, Req>
+    where
+        A: Service<Req>,
+        B: Service<Result<A::Response, A::Error>, Error = A::Error>,
+    {
+        Self(Rc::new((a, b)), PhantomData)
+    }
+}
+
+impl<A, B, Req> Clone for ThenService<A, B, Req> {
+    fn clone(&self) -> Self {
+        ThenService(self.0.clone(), PhantomData)
+    }
+}
+
+impl<A, B, Req> Service<Req> for ThenService<A, B, Req>
+where
+    A: Service<Req>,
+    B: Service<Result<A::Response, A::Error>, Error = A::Error>,
+{
+    type Response = B::Response;
+    type Error = B::Error;
+    type Future = ThenServiceResponse<A, B, Req>;
+
+    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        let (a, b) = &*self.0;
+        let not_ready = !a.poll_ready(cx)?.is_ready();
+        if !b.poll_ready(cx)?.is_ready() || not_ready {
+            Poll::Pending
+        } else {
+            Poll::Ready(Ok(()))
+        }
+    }
+
+    fn call(&self, req: Req) -> Self::Future {
+        ThenServiceResponse {
+            state: State::A {
+                fut: self.0 .0.call(req),
+                b: Some(self.0.clone()),
+            },
+        }
+    }
+}
+
+pin_project! {
+    pub(crate) struct ThenServiceResponse<A, B, Req>
+    where
+        A: Service<Req>,
+        B: Service<Result<A::Response, A::Error>>,
+    {
+        #[pin]
+        state: State<A, B, Req>,
+    }
+}
+
+pin_project! {
+    #[project = StateProj]
+    enum State<A, B, Req>
+    where
+        A: Service<Req>,
+        B: Service<Result<A::Response, A::Error>>,
+    {
+        A { #[pin] fut: A::Future, b: Option<Rc<(A, B)>> },
+        B { #[pin] fut: B::Future },
+    }
+}
+
+impl<A, B, Req> Future for ThenServiceResponse<A, B, Req>
+where
+    A: Service<Req>,
+    B: Service<Result<A::Response, A::Error>>,
+{
+    type Output = Result<B::Response, B::Error>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.as_mut().project();
+
+        match this.state.as_mut().project() {
+            StateProj::A { fut, b } => {
+                let res = ready!(fut.poll(cx));
+                let b = b.take().unwrap();
+                let fut = b.1.call(res);
+                this.state.set(State::B { fut });
+                self.poll(cx)
+            }
+            StateProj::B { fut } => fut.poll(cx),
+        }
+    }
+}
+
+/// `.then()` service factory combinator
+pub(crate) struct ThenServiceFactory<A, B, Req>(Rc<(A, B)>, PhantomData<Req>);
+
+impl<A, B, Req> ThenServiceFactory<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    A::Config: Clone,
+    B: ServiceFactory<
+        Result<A::Response, A::Error>,
+        Config = A::Config,
+        Error = A::Error,
+        InitError = A::InitError,
+    >,
+{
+    /// Create new `AndThen` combinator
+    pub(crate) fn new(a: A, b: B) -> Self {
+        Self(Rc::new((a, b)), PhantomData)
+    }
+}
+
+impl<A, B, Req> ServiceFactory<Req> for ThenServiceFactory<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    A::Config: Clone,
+    B: ServiceFactory<
+        Result<A::Response, A::Error>,
+        Config = A::Config,
+        Error = A::Error,
+        InitError = A::InitError,
+    >,
+{
+    type Response = B::Response;
+    type Error = A::Error;
+
+    type Config = A::Config;
+    type Service = ThenService<A::Service, B::Service, Req>;
+    type InitError = A::InitError;
+    type Future = ThenServiceFactoryResponse<A, B, Req>;
+
+    fn new_service(&self, cfg: A::Config) -> Self::Future {
+        let srv = &*self.0;
+        ThenServiceFactoryResponse::new(srv.0.new_service(cfg.clone()), srv.1.new_service(cfg))
+    }
+}
+
+impl<A, B, Req> Clone for ThenServiceFactory<A, B, Req> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone(), PhantomData)
+    }
+}
+
+pin_project! {
+    pub(crate) struct ThenServiceFactoryResponse<A, B, Req>
+    where
+        A: ServiceFactory<Req>,
+        B: ServiceFactory<
+            Result<A::Response, A::Error>,
+            Config = A::Config,
+            Error = A::Error,
+            InitError = A::InitError,
+        >,
+    {
+        #[pin]
+        fut_b: B::Future,
+        #[pin]
+        fut_a: A::Future,
+        a: Option<A::Service>,
+        b: Option<B::Service>,
+    }
+}
+
+impl<A, B, Req> ThenServiceFactoryResponse<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    B: ServiceFactory<
+        Result<A::Response, A::Error>,
+        Config = A::Config,
+        Error = A::Error,
+        InitError = A::InitError,
+    >,
+{
+    fn new(fut_a: A::Future, fut_b: B::Future) -> Self {
+        Self {
+            fut_a,
+            fut_b,
+            a: None,
+            b: None,
+        }
+    }
+}
+
+impl<A, B, Req> Future for ThenServiceFactoryResponse<A, B, Req>
+where
+    A: ServiceFactory<Req>,
+    B: ServiceFactory<
+        Result<A::Response, A::Error>,
+        Config = A::Config,
+        Error = A::Error,
+        InitError = A::InitError,
+    >,
+{
+    type Output = Result<ThenService<A::Service, B::Service, Req>, A::InitError>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+
+        if this.a.is_none() {
+            if let Poll::Ready(service) = this.fut_a.poll(cx)? {
+                *this.a = Some(service);
+            }
+        }
+        if this.b.is_none() {
+            if let Poll::Ready(service) = this.fut_b.poll(cx)? {
+                *this.b = Some(service);
+            }
+        }
+        if this.a.is_some() && this.b.is_some() {
+            Poll::Ready(Ok(ThenService::new(
+                this.a.take().unwrap(),
+                this.b.take().unwrap(),
+            )))
+        } else {
+            Poll::Pending
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use alloc::rc::Rc;
+    use core::{
+        cell::Cell,
+        task::{Context, Poll},
+    };
+
+    use futures_util::future::lazy;
+
+    use crate::{
+        err, ok,
+        pipeline::{pipeline, pipeline_factory},
+        ready, Ready, Service, ServiceFactory,
+    };
+
+    #[derive(Clone)]
+    struct Srv1(Rc<Cell<usize>>);
+
+    impl Service<Result<&'static str, &'static str>> for Srv1 {
+        type Response = &'static str;
+        type Error = ();
+        type Future = Ready<Result<Self::Response, Self::Error>>;
+
+        fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+            self.0.set(self.0.get() + 1);
+            Poll::Ready(Ok(()))
+        }
+
+        fn call(&self, req: Result<&'static str, &'static str>) -> Self::Future {
+            match req {
+                Ok(msg) => ok(msg),
+                Err(_) => err(()),
+            }
+        }
+    }
+
+    struct Srv2(Rc<Cell<usize>>);
+
+    impl Service<Result<&'static str, ()>> for Srv2 {
+        type Response = (&'static str, &'static str);
+        type Error = ();
+        type Future = Ready<Result<Self::Response, ()>>;
+
+        fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+            self.0.set(self.0.get() + 1);
+            Poll::Ready(Err(()))
+        }
+
+        fn call(&self, req: Result<&'static str, ()>) -> Self::Future {
+            match req {
+                Ok(msg) => ok((msg, "ok")),
+                Err(()) => ok(("srv2", "err")),
+            }
+        }
+    }
+
+    #[actix_rt::test]
+    async fn test_poll_ready() {
+        let cnt = Rc::new(Cell::new(0));
+        let srv = pipeline(Srv1(cnt.clone())).then(Srv2(cnt.clone()));
+        let res = lazy(|cx| srv.poll_ready(cx)).await;
+        assert_eq!(res, Poll::Ready(Err(())));
+        assert_eq!(cnt.get(), 2);
+    }
+
+    #[actix_rt::test]
+    async fn test_call() {
+        let cnt = Rc::new(Cell::new(0));
+        let srv = pipeline(Srv1(cnt.clone())).then(Srv2(cnt));
+
+        let res = srv.call(Ok("srv1")).await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv1", "ok"));
+
+        let res = srv.call(Err("srv")).await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv2", "err"));
+    }
+
+    #[actix_rt::test]
+    async fn test_factory() {
+        let cnt = Rc::new(Cell::new(0));
+        let cnt2 = cnt.clone();
+        let blank = move || ready(Ok::<_, ()>(Srv1(cnt2.clone())));
+        let factory = pipeline_factory(blank).then(move || ready(Ok(Srv2(cnt.clone()))));
+        let srv = factory.new_service(&()).await.unwrap();
+        let res = srv.call(Ok("srv1")).await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv1", "ok"));
+
+        let res = srv.call(Err("srv")).await;
+        assert!(res.is_ok());
+        assert_eq!(res.unwrap(), ("srv2", "err"));
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/transform.rs.html b/src/actix_service/transform.rs.html new file mode 100644 index 00000000..357999fb --- /dev/null +++ b/src/actix_service/transform.rs.html @@ -0,0 +1,543 @@ +transform.rs - source

actix_service/
transform.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
use alloc::{rc::Rc, sync::Arc};
+use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use futures_core::ready;
+use pin_project_lite::pin_project;
+
+use crate::{IntoServiceFactory, Service, ServiceFactory};
+
+/// Apply a [`Transform`] to a [`Service`].
+pub fn apply<T, S, I, Req>(t: T, factory: I) -> ApplyTransform<T, S, Req>
+where
+    I: IntoServiceFactory<S, Req>,
+    S: ServiceFactory<Req>,
+    T: Transform<S::Service, Req, InitError = S::InitError>,
+{
+    ApplyTransform::new(t, factory.into_factory())
+}
+
+/// Defines the interface of a service factory that wraps inner service during construction.
+///
+/// Transformers wrap an inner service and runs during inbound and/or outbound processing in the
+/// service lifecycle. It may modify request and/or response.
+///
+/// For example, a timeout service wrapper:
+///
+/// ```ignore
+/// pub struct Timeout<S> {
+///     service: S,
+///     timeout: Duration,
+/// }
+///
+/// impl<S: Service<Req>, Req> Service<Req> for Timeout<S> {
+///     type Response = S::Response;
+///     type Error = TimeoutError<S::Error>;
+///     type Future = TimeoutServiceResponse<S>;
+///
+///     actix_service::forward_ready!(service);
+///
+///     fn call(&self, req: Req) -> Self::Future {
+///         TimeoutServiceResponse {
+///             fut: self.service.call(req),
+///             sleep: Sleep::new(clock::now() + self.timeout),
+///         }
+///     }
+/// }
+/// ```
+///
+/// This wrapper service is decoupled from the underlying service implementation and could be
+/// applied to any service.
+///
+/// The `Transform` trait defines the interface of a service wrapper. `Transform` is often
+/// implemented for middleware, defining how to construct a middleware Service. A Service that is
+/// constructed by the factory takes the Service that follows it during execution as a parameter,
+/// assuming ownership of the next Service.
+///
+/// A transform for the `Timeout` middleware could look like this:
+///
+/// ```ignore
+/// pub struct TimeoutTransform {
+///     timeout: Duration,
+/// }
+///
+/// impl<S: Service<Req>, Req> Transform<S, Req> for TimeoutTransform {
+///     type Response = S::Response;
+///     type Error = TimeoutError<S::Error>;
+///     type InitError = S::Error;
+///     type Transform = Timeout<S>;
+///     type Future = Ready<Result<Self::Transform, Self::InitError>>;
+///
+///     fn new_transform(&self, service: S) -> Self::Future {
+///         ready(Ok(Timeout {
+///             service,
+///             timeout: self.timeout,
+///         }))
+///     }
+/// }
+/// ```
+pub trait Transform<S, Req> {
+    /// Responses produced by the service.
+    type Response;
+
+    /// Errors produced by the service.
+    type Error;
+
+    /// The `TransformService` value created by this factory
+    type Transform: Service<Req, Response = Self::Response, Error = Self::Error>;
+
+    /// Errors produced while building a transform service.
+    type InitError;
+
+    /// The future response value.
+    type Future: Future<Output = Result<Self::Transform, Self::InitError>>;
+
+    /// Creates and returns a new Transform component, asynchronously
+    fn new_transform(&self, service: S) -> Self::Future;
+}
+
+impl<T, S, Req> Transform<S, Req> for Rc<T>
+where
+    T: Transform<S, Req>,
+{
+    type Response = T::Response;
+    type Error = T::Error;
+    type Transform = T::Transform;
+    type InitError = T::InitError;
+    type Future = T::Future;
+
+    fn new_transform(&self, service: S) -> T::Future {
+        self.as_ref().new_transform(service)
+    }
+}
+
+impl<T, S, Req> Transform<S, Req> for Arc<T>
+where
+    T: Transform<S, Req>,
+{
+    type Response = T::Response;
+    type Error = T::Error;
+    type Transform = T::Transform;
+    type InitError = T::InitError;
+    type Future = T::Future;
+
+    fn new_transform(&self, service: S) -> T::Future {
+        self.as_ref().new_transform(service)
+    }
+}
+
+/// Apply a [`Transform`] to a [`Service`].
+pub struct ApplyTransform<T, S, Req>(Rc<(T, S)>, PhantomData<Req>);
+
+impl<T, S, Req> ApplyTransform<T, S, Req>
+where
+    S: ServiceFactory<Req>,
+    T: Transform<S::Service, Req, InitError = S::InitError>,
+{
+    /// Create new `ApplyTransform` new service instance
+    fn new(t: T, service: S) -> Self {
+        Self(Rc::new((t, service)), PhantomData)
+    }
+}
+
+impl<T, S, Req> Clone for ApplyTransform<T, S, Req> {
+    fn clone(&self) -> Self {
+        ApplyTransform(self.0.clone(), PhantomData)
+    }
+}
+
+impl<T, S, Req> ServiceFactory<Req> for ApplyTransform<T, S, Req>
+where
+    S: ServiceFactory<Req>,
+    T: Transform<S::Service, Req, InitError = S::InitError>,
+{
+    type Response = T::Response;
+    type Error = T::Error;
+
+    type Config = S::Config;
+    type Service = T::Transform;
+    type InitError = T::InitError;
+    type Future = ApplyTransformFuture<T, S, Req>;
+
+    fn new_service(&self, cfg: S::Config) -> Self::Future {
+        ApplyTransformFuture {
+            store: self.0.clone(),
+            state: ApplyTransformFutureState::A {
+                fut: self.0.as_ref().1.new_service(cfg),
+            },
+        }
+    }
+}
+
+pin_project! {
+    pub struct ApplyTransformFuture<T, S, Req>
+    where
+        S: ServiceFactory<Req>,
+        T: Transform<S::Service, Req, InitError = S::InitError>,
+    {
+        store: Rc<(T, S)>,
+        #[pin]
+        state: ApplyTransformFutureState<T, S, Req>,
+    }
+}
+
+pin_project! {
+    #[project = ApplyTransformFutureStateProj]
+    pub enum ApplyTransformFutureState<T, S, Req>
+    where
+        S: ServiceFactory<Req>,
+        T: Transform<S::Service, Req, InitError = S::InitError>,
+    {
+        A { #[pin] fut: S::Future },
+        B { #[pin] fut: T::Future },
+    }
+}
+
+impl<T, S, Req> Future for ApplyTransformFuture<T, S, Req>
+where
+    S: ServiceFactory<Req>,
+    T: Transform<S::Service, Req, InitError = S::InitError>,
+{
+    type Output = Result<T::Transform, T::InitError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.as_mut().project();
+
+        match this.state.as_mut().project() {
+            ApplyTransformFutureStateProj::A { fut } => {
+                let srv = ready!(fut.poll(cx))?;
+                let fut = this.store.0.new_transform(srv);
+                this.state.set(ApplyTransformFutureState::B { fut });
+                self.poll(cx)
+            }
+            ApplyTransformFutureStateProj::B { fut } => fut.poll(cx),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use core::time::Duration;
+
+    use actix_utils::future::{ready, Ready};
+
+    use super::*;
+
+    // pseudo-doctest for Transform trait
+    #[allow(unused)]
+    pub struct TimeoutTransform {
+        timeout: Duration,
+    }
+
+    // pseudo-doctest for Transform trait
+    impl<S: Service<Req>, Req> Transform<S, Req> for TimeoutTransform {
+        type Response = S::Response;
+        type Error = S::Error;
+        type InitError = S::Error;
+        type Transform = Timeout<S>;
+        type Future = Ready<Result<Self::Transform, Self::InitError>>;
+
+        fn new_transform(&self, service: S) -> Self::Future {
+            ready(Ok(Timeout {
+                service,
+                _timeout: self.timeout,
+            }))
+        }
+    }
+
+    // pseudo-doctest for Transform trait
+    #[allow(unused)]
+    pub struct Timeout<S> {
+        service: S,
+        _timeout: Duration,
+    }
+
+    // pseudo-doctest for Transform trait
+    impl<S: Service<Req>, Req> Service<Req> for Timeout<S> {
+        type Response = S::Response;
+        type Error = S::Error;
+        type Future = S::Future;
+
+        crate::forward_ready!(service);
+
+        fn call(&self, req: Req) -> Self::Future {
+            self.service.call(req)
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_service/transform_err.rs.html b/src/actix_service/transform_err.rs.html new file mode 100644 index 00000000..eba32950 --- /dev/null +++ b/src/actix_service/transform_err.rs.html @@ -0,0 +1,191 @@ +transform_err.rs - source

actix_service/
transform_err.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
use core::{
+    future::Future,
+    marker::PhantomData,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use pin_project_lite::pin_project;
+
+use super::Transform;
+
+/// Transform for the [`TransformExt::map_init_err`] combinator, changing the type of a new
+/// [`Transform`]'s initialization error.
+pub struct TransformMapInitErr<T, S, Req, F, E> {
+    transform: T,
+    mapper: F,
+    _phantom: PhantomData<fn(Req) -> (S, E)>,
+}
+
+impl<T, S, F, E, Req> TransformMapInitErr<T, S, Req, F, E> {
+    pub(crate) fn new(t: T, f: F) -> Self
+    where
+        T: Transform<S, Req>,
+        F: Fn(T::InitError) -> E,
+    {
+        Self {
+            transform: t,
+            mapper: f,
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<T, S, Req, F, E> Clone for TransformMapInitErr<T, S, Req, F, E>
+where
+    T: Clone,
+    F: Clone,
+{
+    fn clone(&self) -> Self {
+        Self {
+            transform: self.transform.clone(),
+            mapper: self.mapper.clone(),
+            _phantom: PhantomData,
+        }
+    }
+}
+
+impl<T, S, F, E, Req> Transform<S, Req> for TransformMapInitErr<T, S, Req, F, E>
+where
+    T: Transform<S, Req>,
+    F: Fn(T::InitError) -> E + Clone,
+{
+    type Response = T::Response;
+    type Error = T::Error;
+    type Transform = T::Transform;
+
+    type InitError = E;
+    type Future = TransformMapInitErrFuture<T, S, F, E, Req>;
+
+    fn new_transform(&self, service: S) -> Self::Future {
+        TransformMapInitErrFuture {
+            fut: self.transform.new_transform(service),
+            f: self.mapper.clone(),
+        }
+    }
+}
+
+pin_project! {
+    pub struct TransformMapInitErrFuture<T, S, F, E, Req>
+    where
+    T: Transform<S, Req>,
+    F: Fn(T::InitError) -> E,
+    {
+        #[pin]
+        fut: T::Future,
+        f: F,
+    }
+}
+
+impl<T, S, F, E, Req> Future for TransformMapInitErrFuture<T, S, F, E, Req>
+where
+    T: Transform<S, Req>,
+    F: Fn(T::InitError) -> E + Clone,
+{
+    type Output = Result<T::Transform, E>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+        if let Poll::Ready(res) = this.fut.poll(cx) {
+            Poll::Ready(res.map_err(this.f))
+        } else {
+            Poll::Pending
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/accept/mod.rs.html b/src/actix_tls/accept/mod.rs.html new file mode 100644 index 00000000..b376ff47 --- /dev/null +++ b/src/actix_tls/accept/mod.rs.html @@ -0,0 +1,263 @@ +mod.rs - source

actix_tls/accept/
mod.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
//! TLS connection acceptor services.
+
+use std::{
+    convert::Infallible,
+    error::Error,
+    fmt,
+    sync::atomic::{AtomicUsize, Ordering},
+};
+
+use actix_utils::counter::Counter;
+
+#[cfg(feature = "openssl")]
+pub mod openssl;
+
+#[cfg(feature = "rustls-0_20")]
+pub mod rustls_0_20;
+
+#[doc(hidden)]
+#[cfg(feature = "rustls-0_20")]
+pub use rustls_0_20 as rustls;
+
+#[cfg(feature = "rustls-0_21")]
+pub mod rustls_0_21;
+
+#[cfg(feature = "rustls-0_22")]
+pub mod rustls_0_22;
+
+#[cfg(feature = "rustls-0_23")]
+pub mod rustls_0_23;
+
+#[cfg(feature = "native-tls")]
+pub mod native_tls;
+
+pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
+
+#[cfg(any(
+    feature = "openssl",
+    feature = "rustls-0_20",
+    feature = "rustls-0_21",
+    feature = "rustls-0_22",
+    feature = "rustls-0_23",
+    feature = "native-tls",
+))]
+pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
+    std::time::Duration::from_secs(3);
+
+thread_local! {
+    static MAX_CONN_COUNTER: Counter = Counter::new(MAX_CONN.load(Ordering::Relaxed));
+}
+
+/// Sets the maximum per-worker concurrent TLS connection limit.
+///
+/// All listeners will stop accepting connections when this limit is reached.
+/// It can be used to regulate the global TLS CPU usage.
+///
+/// By default, the connection limit is 256.
+pub fn max_concurrent_tls_connect(num: usize) {
+    MAX_CONN.store(num, Ordering::Relaxed);
+}
+
+/// TLS handshake error, TLS timeout, or inner service error.
+///
+/// All TLS acceptors from this crate will return the `SvcErr` type parameter as [`Infallible`],
+/// which can be cast to your own service type, inferred or otherwise, using [`into_service_error`].
+///
+/// [`into_service_error`]: Self::into_service_error
+#[derive(Debug)]
+pub enum TlsError<TlsErr, SvcErr> {
+    /// TLS handshake has timed-out.
+    Timeout,
+
+    /// Wraps TLS service errors.
+    Tls(TlsErr),
+
+    /// Wraps service errors.
+    Service(SvcErr),
+}
+
+impl<TlsErr> TlsError<TlsErr, Infallible> {
+    /// Casts the infallible service error type returned from acceptors into caller's type.
+    ///
+    /// # Examples
+    /// ```
+    /// # use std::convert::Infallible;
+    /// # use actix_tls::accept::TlsError;
+    /// let a: TlsError<u32, Infallible> = TlsError::Tls(42);
+    /// let _b: TlsError<u32, u64> = a.into_service_error();
+    /// ```
+    pub fn into_service_error<SvcErr>(self) -> TlsError<TlsErr, SvcErr> {
+        match self {
+            Self::Timeout => TlsError::Timeout,
+            Self::Tls(err) => TlsError::Tls(err),
+            Self::Service(err) => match err {},
+        }
+    }
+}
+
+impl<TlsErr, SvcErr> fmt::Display for TlsError<TlsErr, SvcErr> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Timeout => f.write_str("TLS handshake has timed-out"),
+            Self::Tls(_) => f.write_str("TLS handshake error"),
+            Self::Service(_) => f.write_str("Service error"),
+        }
+    }
+}
+
+impl<TlsErr, SvcErr> Error for TlsError<TlsErr, SvcErr>
+where
+    TlsErr: Error + 'static,
+    SvcErr: Error + 'static,
+{
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        match self {
+            TlsError::Tls(err) => Some(err),
+            TlsError::Service(err) => Some(err),
+            TlsError::Timeout => None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn tls_service_error_inference() {
+        let a: TlsError<u32, Infallible> = TlsError::Tls(42);
+        let _b: TlsError<u32, u64> = a.into_service_error();
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/accept/native_tls.rs.html b/src/actix_tls/accept/native_tls.rs.html new file mode 100644 index 00000000..222b16b1 --- /dev/null +++ b/src/actix_tls/accept/native_tls.rs.html @@ -0,0 +1,365 @@ +native_tls.rs - source

actix_tls/accept/
native_tls.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
//! `native-tls` based TLS connection acceptor service.
+//!
+//! See [`Acceptor`] for main service factory docs.
+
+use std::{
+    convert::Infallible,
+    io::{self, IoSlice},
+    pin::Pin,
+    task::{Context, Poll},
+    time::Duration,
+};
+
+use actix_rt::{
+    net::{ActixStream, Ready},
+    time::timeout,
+};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::{
+    counter::Counter,
+    future::{ready, Ready as FutReady},
+};
+use futures_core::future::LocalBoxFuture;
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+use tokio_native_tls::{native_tls::Error, TlsAcceptor};
+
+use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
+
+pub mod reexports {
+    //! Re-exports from `native-tls` that are useful for acceptors.
+
+    pub use tokio_native_tls::{native_tls::Error, TlsAcceptor};
+}
+
+/// Wraps a `native-tls` based async TLS stream in order to implement [`ActixStream`].
+pub struct TlsStream<IO>(tokio_native_tls::TlsStream<IO>);
+
+impl_more::impl_from!(<IO> in tokio_native_tls::TlsStream<IO> => TlsStream<IO>);
+impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_native_tls::TlsStream<IO>);
+
+impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
+    fn poll_read(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &mut ReadBuf<'_>,
+    ) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
+    }
+}
+
+impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
+    fn poll_write(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_flush(cx)
+    }
+
+    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
+    }
+
+    fn poll_write_vectored(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        bufs: &[IoSlice<'_>],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        (**self).is_write_vectored()
+    }
+}
+
+impl<IO: ActixStream> ActixStream for TlsStream<IO> {
+    fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_read_ready((**self).get_ref().get_ref().get_ref(), cx)
+    }
+
+    fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_write_ready((**self).get_ref().get_ref().get_ref(), cx)
+    }
+}
+
+/// Accept TLS connections via the `native-tls` crate.
+pub struct Acceptor {
+    acceptor: TlsAcceptor,
+    handshake_timeout: Duration,
+}
+
+impl Acceptor {
+    /// Constructs `native-tls` based acceptor service factory.
+    pub fn new(acceptor: TlsAcceptor) -> Self {
+        Acceptor {
+            acceptor,
+            handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
+        }
+    }
+
+    /// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
+    ///
+    /// Default timeout is 3 seconds.
+    pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
+        self.handshake_timeout = handshake_timeout;
+        self
+    }
+}
+
+impl Clone for Acceptor {
+    #[inline]
+    fn clone(&self) -> Self {
+        Self {
+            acceptor: self.acceptor.clone(),
+            handshake_timeout: self.handshake_timeout,
+        }
+    }
+}
+
+impl<IO: ActixStream + 'static> ServiceFactory<IO> for Acceptor {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<Error, Infallible>;
+    type Config = ();
+    type Service = AcceptorService;
+    type InitError = ();
+    type Future = FutReady<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        let res = MAX_CONN_COUNTER.with(|conns| {
+            Ok(AcceptorService {
+                acceptor: self.acceptor.clone(),
+                conns: conns.clone(),
+                handshake_timeout: self.handshake_timeout,
+            })
+        });
+
+        ready(res)
+    }
+}
+
+/// Native-TLS based acceptor service.
+pub struct AcceptorService {
+    acceptor: TlsAcceptor,
+    conns: Counter,
+    handshake_timeout: Duration,
+}
+
+impl<IO: ActixStream + 'static> Service<IO> for AcceptorService {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<Error, Infallible>;
+    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
+
+    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        if self.conns.available(cx) {
+            Poll::Ready(Ok(()))
+        } else {
+            Poll::Pending
+        }
+    }
+
+    fn call(&self, io: IO) -> Self::Future {
+        let guard = self.conns.get();
+        let acceptor = self.acceptor.clone();
+
+        let dur = self.handshake_timeout;
+
+        Box::pin(async move {
+            match timeout(dur, acceptor.accept(io)).await {
+                Ok(Ok(io)) => {
+                    drop(guard);
+                    Ok(TlsStream(io))
+                }
+                Ok(Err(err)) => Err(TlsError::Tls(err)),
+                Err(_timeout) => Err(TlsError::Timeout),
+            }
+        })
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/accept/openssl.rs.html b/src/actix_tls/accept/openssl.rs.html new file mode 100644 index 00000000..3395cafa --- /dev/null +++ b/src/actix_tls/accept/openssl.rs.html @@ -0,0 +1,417 @@ +openssl.rs - source

actix_tls/accept/
openssl.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
//! `openssl` based TLS acceptor service.
+//!
+//! See [`Acceptor`] for main service factory docs.
+
+use std::{
+    convert::Infallible,
+    future::Future,
+    io::{self, IoSlice},
+    pin::Pin,
+    task::{Context, Poll},
+    time::Duration,
+};
+
+use actix_rt::{
+    net::{ActixStream, Ready},
+    time::{sleep, Sleep},
+};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::{
+    counter::{Counter, CounterGuard},
+    future::{ready, Ready as FutReady},
+};
+use openssl::ssl::{Error, Ssl, SslAcceptor};
+use pin_project_lite::pin_project;
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+
+use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
+
+pub mod reexports {
+    //! Re-exports from `openssl` that are useful for acceptors.
+
+    pub use openssl::ssl::{
+        AlpnError, Error, HandshakeError, Ssl, SslAcceptor, SslAcceptorBuilder,
+    };
+}
+
+/// Wraps an `openssl` based async TLS stream in order to implement [`ActixStream`].
+pub struct TlsStream<IO>(tokio_openssl::SslStream<IO>);
+
+impl_more::impl_from!(<IO> in tokio_openssl::SslStream<IO> => TlsStream<IO>);
+impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_openssl::SslStream<IO>);
+
+impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
+    fn poll_read(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &mut ReadBuf<'_>,
+    ) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
+    }
+}
+
+impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
+    fn poll_write(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_flush(cx)
+    }
+
+    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
+    }
+
+    fn poll_write_vectored(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        bufs: &[IoSlice<'_>],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        (**self).is_write_vectored()
+    }
+}
+
+impl<IO: ActixStream> ActixStream for TlsStream<IO> {
+    fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_read_ready((**self).get_ref(), cx)
+    }
+
+    fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_write_ready((**self).get_ref(), cx)
+    }
+}
+
+/// Accept TLS connections via the `openssl` crate.
+pub struct Acceptor {
+    acceptor: SslAcceptor,
+    handshake_timeout: Duration,
+}
+
+impl Acceptor {
+    /// Create `openssl` based acceptor service factory.
+    #[inline]
+    pub fn new(acceptor: SslAcceptor) -> Self {
+        Acceptor {
+            acceptor,
+            handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
+        }
+    }
+
+    /// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
+    ///
+    /// Default timeout is 3 seconds.
+    pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
+        self.handshake_timeout = handshake_timeout;
+        self
+    }
+}
+
+impl Clone for Acceptor {
+    #[inline]
+    fn clone(&self) -> Self {
+        Self {
+            acceptor: self.acceptor.clone(),
+            handshake_timeout: self.handshake_timeout,
+        }
+    }
+}
+
+impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<Error, Infallible>;
+    type Config = ();
+    type Service = AcceptorService;
+    type InitError = ();
+    type Future = FutReady<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        let res = MAX_CONN_COUNTER.with(|conns| {
+            Ok(AcceptorService {
+                acceptor: self.acceptor.clone(),
+                conns: conns.clone(),
+                handshake_timeout: self.handshake_timeout,
+            })
+        });
+
+        ready(res)
+    }
+}
+
+/// OpenSSL based acceptor service.
+pub struct AcceptorService {
+    acceptor: SslAcceptor,
+    conns: Counter,
+    handshake_timeout: Duration,
+}
+
+impl<IO: ActixStream> Service<IO> for AcceptorService {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<Error, Infallible>;
+    type Future = AcceptFut<IO>;
+
+    fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        if self.conns.available(ctx) {
+            Poll::Ready(Ok(()))
+        } else {
+            Poll::Pending
+        }
+    }
+
+    fn call(&self, io: IO) -> Self::Future {
+        let ssl_ctx = self.acceptor.context();
+        let ssl = Ssl::new(ssl_ctx).expect("Provided SSL acceptor was invalid.");
+
+        AcceptFut {
+            _guard: self.conns.get(),
+            timeout: sleep(self.handshake_timeout),
+            stream: Some(tokio_openssl::SslStream::new(ssl, io).unwrap()),
+        }
+    }
+}
+
+pin_project! {
+    /// Accept future for OpenSSL service.
+    #[doc(hidden)]
+    pub struct AcceptFut<IO: ActixStream> {
+        stream: Option<tokio_openssl::SslStream<IO>>,
+        #[pin]
+        timeout: Sleep,
+        _guard: CounterGuard,
+    }
+}
+
+impl<IO: ActixStream> Future for AcceptFut<IO> {
+    type Output = Result<TlsStream<IO>, TlsError<Error, Infallible>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.project();
+
+        match Pin::new(this.stream.as_mut().unwrap()).poll_accept(cx) {
+            Poll::Ready(Ok(())) => Poll::Ready(Ok(this
+                .stream
+                .take()
+                .expect("Acceptor should not be polled after it has completed.")
+                .into())),
+            Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
+            Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/accept/rustls_0_20.rs.html b/src/actix_tls/accept/rustls_0_20.rs.html new file mode 100644 index 00000000..37a95507 --- /dev/null +++ b/src/actix_tls/accept/rustls_0_20.rs.html @@ -0,0 +1,397 @@ +rustls_0_20.rs - source

actix_tls/accept/
rustls_0_20.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
//! `rustls` v0.20 based TLS connection acceptor service.
+//!
+//! See [`Acceptor`] for main service factory docs.
+
+use std::{
+    convert::Infallible,
+    future::Future,
+    io::{self, IoSlice},
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+    time::Duration,
+};
+
+use actix_rt::{
+    net::{ActixStream, Ready},
+    time::{sleep, Sleep},
+};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::{
+    counter::{Counter, CounterGuard},
+    future::{ready, Ready as FutReady},
+};
+use pin_project_lite::pin_project;
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+use tokio_rustls::{Accept, TlsAcceptor};
+use tokio_rustls_023 as tokio_rustls;
+
+use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
+
+pub mod reexports {
+    //! Re-exports from `rustls` that are useful for acceptors.
+
+    pub use tokio_rustls_023::rustls::ServerConfig;
+}
+
+/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
+pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
+
+impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
+impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
+
+impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
+    fn poll_read(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &mut ReadBuf<'_>,
+    ) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
+    }
+}
+
+impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
+    fn poll_write(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_flush(cx)
+    }
+
+    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
+    }
+
+    fn poll_write_vectored(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        bufs: &[IoSlice<'_>],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        (**self).is_write_vectored()
+    }
+}
+
+impl<IO: ActixStream> ActixStream for TlsStream<IO> {
+    fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_read_ready((**self).get_ref().0, cx)
+    }
+
+    fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_write_ready((**self).get_ref().0, cx)
+    }
+}
+
+/// Accept TLS connections via the `rustls` crate.
+pub struct Acceptor {
+    config: Arc<reexports::ServerConfig>,
+    handshake_timeout: Duration,
+}
+
+impl Acceptor {
+    /// Constructs `rustls` based acceptor service factory.
+    pub fn new(config: reexports::ServerConfig) -> Self {
+        Acceptor {
+            config: Arc::new(config),
+            handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
+        }
+    }
+
+    /// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
+    ///
+    /// Default timeout is 3 seconds.
+    pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
+        self.handshake_timeout = handshake_timeout;
+        self
+    }
+}
+
+impl Clone for Acceptor {
+    fn clone(&self) -> Self {
+        Self {
+            config: self.config.clone(),
+            handshake_timeout: self.handshake_timeout,
+        }
+    }
+}
+
+impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Config = ();
+    type Service = AcceptorService;
+    type InitError = ();
+    type Future = FutReady<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        let res = MAX_CONN_COUNTER.with(|conns| {
+            Ok(AcceptorService {
+                acceptor: self.config.clone().into(),
+                conns: conns.clone(),
+                handshake_timeout: self.handshake_timeout,
+            })
+        });
+
+        ready(res)
+    }
+}
+
+/// Rustls based acceptor service.
+pub struct AcceptorService {
+    acceptor: TlsAcceptor,
+    conns: Counter,
+    handshake_timeout: Duration,
+}
+
+impl<IO: ActixStream> Service<IO> for AcceptorService {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Future = AcceptFut<IO>;
+
+    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        if self.conns.available(cx) {
+            Poll::Ready(Ok(()))
+        } else {
+            Poll::Pending
+        }
+    }
+
+    fn call(&self, req: IO) -> Self::Future {
+        AcceptFut {
+            fut: self.acceptor.accept(req),
+            timeout: sleep(self.handshake_timeout),
+            _guard: self.conns.get(),
+        }
+    }
+}
+
+pin_project! {
+    /// Accept future for Rustls service.
+    #[doc(hidden)]
+    pub struct AcceptFut<IO: ActixStream> {
+        fut: Accept<IO>,
+        #[pin]
+        timeout: Sleep,
+        _guard: CounterGuard,
+    }
+}
+
+impl<IO: ActixStream> Future for AcceptFut<IO> {
+    type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.project();
+        match Pin::new(&mut this.fut).poll(cx) {
+            Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
+            Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
+            Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/accept/rustls_0_21.rs.html b/src/actix_tls/accept/rustls_0_21.rs.html new file mode 100644 index 00000000..440e7723 --- /dev/null +++ b/src/actix_tls/accept/rustls_0_21.rs.html @@ -0,0 +1,397 @@ +rustls_0_21.rs - source

actix_tls/accept/
rustls_0_21.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
//! `rustls` v0.21 based TLS connection acceptor service.
+//!
+//! See [`Acceptor`] for main service factory docs.
+
+use std::{
+    convert::Infallible,
+    future::Future,
+    io::{self, IoSlice},
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+    time::Duration,
+};
+
+use actix_rt::{
+    net::{ActixStream, Ready},
+    time::{sleep, Sleep},
+};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::{
+    counter::{Counter, CounterGuard},
+    future::{ready, Ready as FutReady},
+};
+use pin_project_lite::pin_project;
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+use tokio_rustls::{Accept, TlsAcceptor};
+use tokio_rustls_024 as tokio_rustls;
+
+use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
+
+pub mod reexports {
+    //! Re-exports from `rustls` that are useful for acceptors.
+
+    pub use tokio_rustls_024::rustls::ServerConfig;
+}
+
+/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
+pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
+
+impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
+impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
+
+impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
+    fn poll_read(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &mut ReadBuf<'_>,
+    ) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
+    }
+}
+
+impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
+    fn poll_write(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_flush(cx)
+    }
+
+    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
+    }
+
+    fn poll_write_vectored(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        bufs: &[IoSlice<'_>],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        (**self).is_write_vectored()
+    }
+}
+
+impl<IO: ActixStream> ActixStream for TlsStream<IO> {
+    fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_read_ready((**self).get_ref().0, cx)
+    }
+
+    fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_write_ready((**self).get_ref().0, cx)
+    }
+}
+
+/// Accept TLS connections via the `rustls` crate.
+pub struct Acceptor {
+    config: Arc<reexports::ServerConfig>,
+    handshake_timeout: Duration,
+}
+
+impl Acceptor {
+    /// Constructs `rustls` based acceptor service factory.
+    pub fn new(config: reexports::ServerConfig) -> Self {
+        Acceptor {
+            config: Arc::new(config),
+            handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
+        }
+    }
+
+    /// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
+    ///
+    /// Default timeout is 3 seconds.
+    pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
+        self.handshake_timeout = handshake_timeout;
+        self
+    }
+}
+
+impl Clone for Acceptor {
+    fn clone(&self) -> Self {
+        Self {
+            config: self.config.clone(),
+            handshake_timeout: self.handshake_timeout,
+        }
+    }
+}
+
+impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Config = ();
+    type Service = AcceptorService;
+    type InitError = ();
+    type Future = FutReady<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        let res = MAX_CONN_COUNTER.with(|conns| {
+            Ok(AcceptorService {
+                acceptor: self.config.clone().into(),
+                conns: conns.clone(),
+                handshake_timeout: self.handshake_timeout,
+            })
+        });
+
+        ready(res)
+    }
+}
+
+/// Rustls based acceptor service.
+pub struct AcceptorService {
+    acceptor: TlsAcceptor,
+    conns: Counter,
+    handshake_timeout: Duration,
+}
+
+impl<IO: ActixStream> Service<IO> for AcceptorService {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Future = AcceptFut<IO>;
+
+    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        if self.conns.available(cx) {
+            Poll::Ready(Ok(()))
+        } else {
+            Poll::Pending
+        }
+    }
+
+    fn call(&self, req: IO) -> Self::Future {
+        AcceptFut {
+            fut: self.acceptor.accept(req),
+            timeout: sleep(self.handshake_timeout),
+            _guard: self.conns.get(),
+        }
+    }
+}
+
+pin_project! {
+    /// Accept future for Rustls service.
+    #[doc(hidden)]
+    pub struct AcceptFut<IO: ActixStream> {
+        fut: Accept<IO>,
+        #[pin]
+        timeout: Sleep,
+        _guard: CounterGuard,
+    }
+}
+
+impl<IO: ActixStream> Future for AcceptFut<IO> {
+    type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.project();
+        match Pin::new(&mut this.fut).poll(cx) {
+            Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
+            Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
+            Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/accept/rustls_0_22.rs.html b/src/actix_tls/accept/rustls_0_22.rs.html new file mode 100644 index 00000000..ad2bc85f --- /dev/null +++ b/src/actix_tls/accept/rustls_0_22.rs.html @@ -0,0 +1,397 @@ +rustls_0_22.rs - source

actix_tls/accept/
rustls_0_22.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
//! `rustls` v0.22 based TLS connection acceptor service.
+//!
+//! See [`Acceptor`] for main service factory docs.
+
+use std::{
+    convert::Infallible,
+    future::Future,
+    io::{self, IoSlice},
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+    time::Duration,
+};
+
+use actix_rt::{
+    net::{ActixStream, Ready},
+    time::{sleep, Sleep},
+};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::{
+    counter::{Counter, CounterGuard},
+    future::{ready, Ready as FutReady},
+};
+use pin_project_lite::pin_project;
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+use tokio_rustls::{Accept, TlsAcceptor};
+use tokio_rustls_025 as tokio_rustls;
+
+use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
+
+pub mod reexports {
+    //! Re-exports from `rustls` that are useful for acceptors.
+
+    pub use tokio_rustls_025::rustls::ServerConfig;
+}
+
+/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
+pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
+
+impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
+impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
+
+impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
+    fn poll_read(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &mut ReadBuf<'_>,
+    ) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
+    }
+}
+
+impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
+    fn poll_write(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_flush(cx)
+    }
+
+    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
+    }
+
+    fn poll_write_vectored(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        bufs: &[IoSlice<'_>],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        (**self).is_write_vectored()
+    }
+}
+
+impl<IO: ActixStream> ActixStream for TlsStream<IO> {
+    fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_read_ready((**self).get_ref().0, cx)
+    }
+
+    fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_write_ready((**self).get_ref().0, cx)
+    }
+}
+
+/// Accept TLS connections via the `rustls` crate.
+pub struct Acceptor {
+    config: Arc<reexports::ServerConfig>,
+    handshake_timeout: Duration,
+}
+
+impl Acceptor {
+    /// Constructs `rustls` based acceptor service factory.
+    pub fn new(config: reexports::ServerConfig) -> Self {
+        Acceptor {
+            config: Arc::new(config),
+            handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
+        }
+    }
+
+    /// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
+    ///
+    /// Default timeout is 3 seconds.
+    pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
+        self.handshake_timeout = handshake_timeout;
+        self
+    }
+}
+
+impl Clone for Acceptor {
+    fn clone(&self) -> Self {
+        Self {
+            config: self.config.clone(),
+            handshake_timeout: self.handshake_timeout,
+        }
+    }
+}
+
+impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Config = ();
+    type Service = AcceptorService;
+    type InitError = ();
+    type Future = FutReady<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        let res = MAX_CONN_COUNTER.with(|conns| {
+            Ok(AcceptorService {
+                acceptor: self.config.clone().into(),
+                conns: conns.clone(),
+                handshake_timeout: self.handshake_timeout,
+            })
+        });
+
+        ready(res)
+    }
+}
+
+/// Rustls based acceptor service.
+pub struct AcceptorService {
+    acceptor: TlsAcceptor,
+    conns: Counter,
+    handshake_timeout: Duration,
+}
+
+impl<IO: ActixStream> Service<IO> for AcceptorService {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Future = AcceptFut<IO>;
+
+    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        if self.conns.available(cx) {
+            Poll::Ready(Ok(()))
+        } else {
+            Poll::Pending
+        }
+    }
+
+    fn call(&self, req: IO) -> Self::Future {
+        AcceptFut {
+            fut: self.acceptor.accept(req),
+            timeout: sleep(self.handshake_timeout),
+            _guard: self.conns.get(),
+        }
+    }
+}
+
+pin_project! {
+    /// Accept future for Rustls service.
+    #[doc(hidden)]
+    pub struct AcceptFut<IO: ActixStream> {
+        fut: Accept<IO>,
+        #[pin]
+        timeout: Sleep,
+        _guard: CounterGuard,
+    }
+}
+
+impl<IO: ActixStream> Future for AcceptFut<IO> {
+    type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.project();
+        match Pin::new(&mut this.fut).poll(cx) {
+            Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
+            Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
+            Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/accept/rustls_0_23.rs.html b/src/actix_tls/accept/rustls_0_23.rs.html new file mode 100644 index 00000000..605dc65e --- /dev/null +++ b/src/actix_tls/accept/rustls_0_23.rs.html @@ -0,0 +1,397 @@ +rustls_0_23.rs - source

actix_tls/accept/
rustls_0_23.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
//! `rustls` v0.23 based TLS connection acceptor service.
+//!
+//! See [`Acceptor`] for main service factory docs.
+
+use std::{
+    convert::Infallible,
+    future::Future,
+    io::{self, IoSlice},
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+    time::Duration,
+};
+
+use actix_rt::{
+    net::{ActixStream, Ready},
+    time::{sleep, Sleep},
+};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::{
+    counter::{Counter, CounterGuard},
+    future::{ready, Ready as FutReady},
+};
+use pin_project_lite::pin_project;
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+use tokio_rustls::{Accept, TlsAcceptor};
+use tokio_rustls_026 as tokio_rustls;
+
+use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
+
+pub mod reexports {
+    //! Re-exports from `rustls` that are useful for acceptors.
+
+    pub use tokio_rustls_026::rustls::ServerConfig;
+}
+
+/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
+pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
+
+impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
+impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
+
+impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
+    fn poll_read(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &mut ReadBuf<'_>,
+    ) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
+    }
+}
+
+impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
+    fn poll_write(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_flush(cx)
+    }
+
+    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
+        Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
+    }
+
+    fn poll_write_vectored(
+        self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        bufs: &[IoSlice<'_>],
+    ) -> Poll<io::Result<usize>> {
+        Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
+    }
+
+    fn is_write_vectored(&self) -> bool {
+        (**self).is_write_vectored()
+    }
+}
+
+impl<IO: ActixStream> ActixStream for TlsStream<IO> {
+    fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_read_ready((**self).get_ref().0, cx)
+    }
+
+    fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
+        IO::poll_write_ready((**self).get_ref().0, cx)
+    }
+}
+
+/// Accept TLS connections via the `rustls` crate.
+pub struct Acceptor {
+    config: Arc<reexports::ServerConfig>,
+    handshake_timeout: Duration,
+}
+
+impl Acceptor {
+    /// Constructs `rustls` based acceptor service factory.
+    pub fn new(config: reexports::ServerConfig) -> Self {
+        Acceptor {
+            config: Arc::new(config),
+            handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
+        }
+    }
+
+    /// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
+    ///
+    /// Default timeout is 3 seconds.
+    pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
+        self.handshake_timeout = handshake_timeout;
+        self
+    }
+}
+
+impl Clone for Acceptor {
+    fn clone(&self) -> Self {
+        Self {
+            config: self.config.clone(),
+            handshake_timeout: self.handshake_timeout,
+        }
+    }
+}
+
+impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Config = ();
+    type Service = AcceptorService;
+    type InitError = ();
+    type Future = FutReady<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        let res = MAX_CONN_COUNTER.with(|conns| {
+            Ok(AcceptorService {
+                acceptor: self.config.clone().into(),
+                conns: conns.clone(),
+                handshake_timeout: self.handshake_timeout,
+            })
+        });
+
+        ready(res)
+    }
+}
+
+/// Rustls based acceptor service.
+pub struct AcceptorService {
+    acceptor: TlsAcceptor,
+    conns: Counter,
+    handshake_timeout: Duration,
+}
+
+impl<IO: ActixStream> Service<IO> for AcceptorService {
+    type Response = TlsStream<IO>;
+    type Error = TlsError<io::Error, Infallible>;
+    type Future = AcceptFut<IO>;
+
+    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        if self.conns.available(cx) {
+            Poll::Ready(Ok(()))
+        } else {
+            Poll::Pending
+        }
+    }
+
+    fn call(&self, req: IO) -> Self::Future {
+        AcceptFut {
+            fut: self.acceptor.accept(req),
+            timeout: sleep(self.handshake_timeout),
+            _guard: self.conns.get(),
+        }
+    }
+}
+
+pin_project! {
+    /// Accept future for Rustls service.
+    #[doc(hidden)]
+    pub struct AcceptFut<IO: ActixStream> {
+        fut: Accept<IO>,
+        #[pin]
+        timeout: Sleep,
+        _guard: CounterGuard,
+    }
+}
+
+impl<IO: ActixStream> Future for AcceptFut<IO> {
+    type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let mut this = self.project();
+        match Pin::new(&mut this.fut).poll(cx) {
+            Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
+            Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
+            Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/connect_addrs.rs.html b/src/actix_tls/connect/connect_addrs.rs.html new file mode 100644 index 00000000..1d90c0cf --- /dev/null +++ b/src/actix_tls/connect/connect_addrs.rs.html @@ -0,0 +1,165 @@ +connect_addrs.rs - source

actix_tls/connect/
connect_addrs.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
use std::{
+    collections::{vec_deque, VecDeque},
+    fmt, iter,
+    net::SocketAddr,
+};
+
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub(crate) enum ConnectAddrs {
+    None,
+    One(SocketAddr),
+    // TODO: consider using smallvec
+    Multi(VecDeque<SocketAddr>),
+}
+
+impl ConnectAddrs {
+    pub(crate) fn is_unresolved(&self) -> bool {
+        matches!(self, Self::None)
+    }
+
+    pub(crate) fn is_resolved(&self) -> bool {
+        !self.is_unresolved()
+    }
+}
+
+impl Default for ConnectAddrs {
+    fn default() -> Self {
+        Self::None
+    }
+}
+
+impl From<Option<SocketAddr>> for ConnectAddrs {
+    fn from(addr: Option<SocketAddr>) -> Self {
+        match addr {
+            Some(addr) => ConnectAddrs::One(addr),
+            None => ConnectAddrs::None,
+        }
+    }
+}
+
+/// Iterator over addresses in a [`Connect`] request.
+#[derive(Clone)]
+pub(crate) enum ConnectAddrsIter<'a> {
+    None,
+    One(SocketAddr),
+    Multi(vec_deque::Iter<'a, SocketAddr>),
+    MultiOwned(vec_deque::IntoIter<SocketAddr>),
+}
+
+impl Iterator for ConnectAddrsIter<'_> {
+    type Item = SocketAddr;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match *self {
+            Self::None => None,
+            Self::One(addr) => {
+                *self = Self::None;
+                Some(addr)
+            }
+            Self::Multi(ref mut iter) => iter.next().copied(),
+            Self::MultiOwned(ref mut iter) => iter.next(),
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        match *self {
+            Self::None => (0, Some(0)),
+            Self::One(_) => (1, Some(1)),
+            Self::Multi(ref iter) => iter.size_hint(),
+            Self::MultiOwned(ref iter) => iter.size_hint(),
+        }
+    }
+}
+
+impl fmt::Debug for ConnectAddrsIter<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.clone()).finish()
+    }
+}
+
+impl iter::ExactSizeIterator for ConnectAddrsIter<'_> {}
+
+impl iter::FusedIterator for ConnectAddrsIter<'_> {}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/connection.rs.html b/src/actix_tls/connect/connection.rs.html new file mode 100644 index 00000000..b722389f --- /dev/null +++ b/src/actix_tls/connect/connection.rs.html @@ -0,0 +1,103 @@ +connection.rs - source

actix_tls/connect/
connection.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
use super::Host;
+
+/// Wraps underlying I/O and the connection request that initiated it.
+#[derive(Debug)]
+pub struct Connection<R, IO> {
+    pub(crate) req: R,
+    pub(crate) io: IO,
+}
+
+impl_more::impl_deref_and_mut!(<R, IO> in Connection<R, IO> => io: IO);
+
+impl<R, IO> Connection<R, IO> {
+    /// Construct new `Connection` from request and IO parts.
+    pub fn new(req: R, io: IO) -> Self {
+        Self { req, io }
+    }
+}
+
+impl<R, IO> Connection<R, IO> {
+    /// Deconstructs into IO and request parts.
+    pub fn into_parts(self) -> (IO, R) {
+        (self.io, self.req)
+    }
+
+    /// Replaces underlying IO, returning old IO and new `Connection`.
+    pub fn replace_io<IO2>(self, io: IO2) -> (IO, Connection<R, IO2>) {
+        (self.io, Connection { io, req: self.req })
+    }
+
+    /// Returns a shared reference to the underlying IO.
+    pub fn io_ref(&self) -> &IO {
+        &self.io
+    }
+
+    /// Returns a mutable reference to the underlying IO.
+    pub fn io_mut(&mut self) -> &mut IO {
+        &mut self.io
+    }
+
+    /// Returns a reference to the connection request.
+    pub fn request(&self) -> &R {
+        &self.req
+    }
+}
+
+impl<R: Host, IO> Connection<R, IO> {
+    /// Returns hostname.
+    pub fn hostname(&self) -> &str {
+        self.req.hostname()
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/connector.rs.html b/src/actix_tls/connect/connector.rs.html new file mode 100644 index 00000000..38f0701d --- /dev/null +++ b/src/actix_tls/connect/connector.rs.html @@ -0,0 +1,257 @@ +connector.rs - source

actix_tls/connect/
connector.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
use std::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use actix_rt::net::TcpStream;
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::ready;
+
+use super::{
+    error::ConnectError,
+    resolver::{Resolver, ResolverService},
+    tcp::{TcpConnector, TcpConnectorService},
+    ConnectInfo, Connection, Host,
+};
+
+/// Combined resolver and TCP connector service factory.
+///
+/// Used to create [`ConnectorService`]s which receive connection information, resolve DNS if
+/// required, and return a TCP stream.
+#[derive(Clone, Default)]
+pub struct Connector {
+    resolver: Resolver,
+}
+
+impl Connector {
+    /// Constructs new connector factory with the given resolver.
+    pub fn new(resolver: Resolver) -> Self {
+        Connector { resolver }
+    }
+
+    /// Build connector service.
+    pub fn service(&self) -> ConnectorService {
+        ConnectorService {
+            tcp: TcpConnector::default().service(),
+            resolver: self.resolver.service(),
+        }
+    }
+}
+
+impl<R: Host> ServiceFactory<ConnectInfo<R>> for Connector {
+    type Response = Connection<R, TcpStream>;
+    type Error = ConnectError;
+    type Config = ();
+    type Service = ConnectorService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(self.service())
+    }
+}
+
+/// Combined resolver and TCP connector service.
+///
+/// Service implementation receives connection information, resolves DNS if required, and returns
+/// a TCP stream.
+#[derive(Clone, Default)]
+pub struct ConnectorService {
+    tcp: TcpConnectorService,
+    resolver: ResolverService,
+}
+
+impl<R: Host> Service<ConnectInfo<R>> for ConnectorService {
+    type Response = Connection<R, TcpStream>;
+    type Error = ConnectError;
+    type Future = ConnectServiceResponse<R>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, req: ConnectInfo<R>) -> Self::Future {
+        ConnectServiceResponse {
+            fut: ConnectFut::Resolve(self.resolver.call(req)),
+            tcp: self.tcp,
+        }
+    }
+}
+
+/// Chains futures of resolve and connect steps.
+pub(crate) enum ConnectFut<R: Host> {
+    Resolve(<ResolverService as Service<ConnectInfo<R>>>::Future),
+    Connect(<TcpConnectorService as Service<ConnectInfo<R>>>::Future),
+}
+
+/// Container for the intermediate states of [`ConnectFut`].
+pub(crate) enum ConnectFutState<R: Host> {
+    Resolved(ConnectInfo<R>),
+    Connected(Connection<R, TcpStream>),
+}
+
+impl<R: Host> ConnectFut<R> {
+    fn poll_connect(
+        &mut self,
+        cx: &mut Context<'_>,
+    ) -> Poll<Result<ConnectFutState<R>, ConnectError>> {
+        match self {
+            ConnectFut::Resolve(ref mut fut) => {
+                Pin::new(fut).poll(cx).map_ok(ConnectFutState::Resolved)
+            }
+
+            ConnectFut::Connect(ref mut fut) => {
+                Pin::new(fut).poll(cx).map_ok(ConnectFutState::Connected)
+            }
+        }
+    }
+}
+
+pub struct ConnectServiceResponse<R: Host> {
+    fut: ConnectFut<R>,
+    tcp: TcpConnectorService,
+}
+
+impl<R: Host> Future for ConnectServiceResponse<R> {
+    type Output = Result<Connection<R, TcpStream>, ConnectError>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        loop {
+            match ready!(self.fut.poll_connect(cx))? {
+                ConnectFutState::Resolved(res) => {
+                    self.fut = ConnectFut::Connect(self.tcp.call(res));
+                }
+                ConnectFutState::Connected(res) => return Poll::Ready(Ok(res)),
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/error.rs.html b/src/actix_tls/connect/error.rs.html new file mode 100644 index 00000000..fc981ff2 --- /dev/null +++ b/src/actix_tls/connect/error.rs.html @@ -0,0 +1,89 @@ +error.rs - source

actix_tls/connect/
error.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
use std::{error::Error, fmt, io};
+
+/// Errors that can result from using a connector service.
+#[derive(Debug)]
+pub enum ConnectError {
+    /// Failed to resolve the hostname.
+    Resolver(Box<dyn std::error::Error>),
+
+    /// No DNS records.
+    NoRecords,
+
+    /// Invalid input.
+    InvalidInput,
+
+    /// Unresolved host name.
+    Unresolved,
+
+    /// Connection IO error.
+    Io(io::Error),
+}
+
+impl fmt::Display for ConnectError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::NoRecords => f.write_str("No DNS records found for the input"),
+            Self::InvalidInput => f.write_str("Invalid input"),
+            Self::Unresolved => {
+                f.write_str("Connector received `Connect` method with unresolved host")
+            }
+            Self::Resolver(_) => f.write_str("Failed to resolve hostname"),
+            Self::Io(_) => f.write_str("I/O error"),
+        }
+    }
+}
+
+impl Error for ConnectError {
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        match self {
+            Self::Resolver(err) => Some(&**err),
+            Self::Io(err) => Some(err),
+            Self::NoRecords | Self::InvalidInput | Self::Unresolved => None,
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/host.rs.html b/src/actix_tls/connect/host.rs.html new file mode 100644 index 00000000..9802cae8 --- /dev/null +++ b/src/actix_tls/connect/host.rs.html @@ -0,0 +1,143 @@ +host.rs - source

actix_tls/connect/
host.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
//! The [`Host`] trait.
+
+/// An interface for types where host parts (hostname and port) can be derived.
+///
+/// The [WHATWG URL Standard] defines the terminology used for this trait and its methods.
+///
+/// ```plain
+/// +------------------------+
+/// |          host          |
+/// +-----------------+------+
+/// |    hostname     | port |
+/// |                 |      |
+/// | sub.example.com : 8080 |
+/// +-----------------+------+
+/// ```
+///
+/// [WHATWG URL Standard]: https://url.spec.whatwg.org/
+pub trait Host: Unpin + 'static {
+    /// Extract hostname.
+    fn hostname(&self) -> &str;
+
+    /// Extract optional port.
+    fn port(&self) -> Option<u16> {
+        None
+    }
+}
+
+impl Host for String {
+    fn hostname(&self) -> &str {
+        self.split_once(':')
+            .map(|(hostname, _)| hostname)
+            .unwrap_or(self)
+    }
+
+    fn port(&self) -> Option<u16> {
+        self.split_once(':').and_then(|(_, port)| port.parse().ok())
+    }
+}
+
+impl Host for &'static str {
+    fn hostname(&self) -> &str {
+        self.split_once(':')
+            .map(|(hostname, _)| hostname)
+            .unwrap_or(self)
+    }
+
+    fn port(&self) -> Option<u16> {
+        self.split_once(':').and_then(|(_, port)| port.parse().ok())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    macro_rules! assert_connection_info_eq {
+        ($req:expr, $hostname:expr, $port:expr) => {{
+            assert_eq!($req.hostname(), $hostname);
+            assert_eq!($req.port(), $port);
+        }};
+    }
+
+    #[test]
+    fn host_parsing() {
+        assert_connection_info_eq!("example.com", "example.com", None);
+        assert_connection_info_eq!("example.com:8080", "example.com", Some(8080));
+        assert_connection_info_eq!("example:8080", "example", Some(8080));
+        assert_connection_info_eq!("example.com:false", "example.com", None);
+        assert_connection_info_eq!("example.com:false:false", "example.com", None);
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/info.rs.html b/src/actix_tls/connect/info.rs.html new file mode 100644 index 00000000..d85a1436 --- /dev/null +++ b/src/actix_tls/connect/info.rs.html @@ -0,0 +1,503 @@ +info.rs - source

actix_tls/connect/
info.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
//! Connection info struct.
+
+use std::{
+    collections::VecDeque,
+    fmt,
+    iter::{self, FromIterator as _},
+    mem,
+    net::{IpAddr, SocketAddr},
+};
+
+use super::{
+    connect_addrs::{ConnectAddrs, ConnectAddrsIter},
+    Host,
+};
+
+/// Connection request information.
+///
+/// May contain known/pre-resolved socket address(es) or a host that needs resolving with DNS.
+#[derive(Debug, PartialEq, Eq, Hash)]
+pub struct ConnectInfo<R> {
+    pub(crate) request: R,
+    pub(crate) port: u16,
+    pub(crate) addr: ConnectAddrs,
+    pub(crate) local_addr: Option<IpAddr>,
+}
+
+impl<R: Host> ConnectInfo<R> {
+    /// Constructs new connection info using a request.
+    pub fn new(request: R) -> ConnectInfo<R> {
+        let port = request.port();
+
+        ConnectInfo {
+            request,
+            port: port.unwrap_or(0),
+            addr: ConnectAddrs::None,
+            local_addr: None,
+        }
+    }
+
+    /// Constructs new connection info from request and known socket address.
+    ///
+    /// Since socket address is known, [`Connector`](super::Connector) will skip the DNS
+    /// resolution step.
+    pub fn with_addr(request: R, addr: SocketAddr) -> ConnectInfo<R> {
+        ConnectInfo {
+            request,
+            port: 0,
+            addr: ConnectAddrs::One(addr),
+            local_addr: None,
+        }
+    }
+
+    /// Set connection port.
+    ///
+    /// If request provided a port, this will override it.
+    pub fn set_port(mut self, port: u16) -> Self {
+        self.port = port;
+        self
+    }
+
+    /// Set connection socket address.
+    pub fn set_addr(mut self, addr: impl Into<Option<SocketAddr>>) -> Self {
+        self.addr = ConnectAddrs::from(addr.into());
+        self
+    }
+
+    /// Set list of addresses.
+    pub fn set_addrs<I>(mut self, addrs: I) -> Self
+    where
+        I: IntoIterator<Item = SocketAddr>,
+    {
+        let mut addrs = VecDeque::from_iter(addrs);
+        self.addr = if addrs.len() < 2 {
+            ConnectAddrs::from(addrs.pop_front())
+        } else {
+            ConnectAddrs::Multi(addrs)
+        };
+        self
+    }
+
+    /// Set local address to connection with.
+    ///
+    /// Useful in situations where the IP address bound to a particular network interface is known.
+    /// This would make sure the socket is opened through that interface.
+    pub fn set_local_addr(mut self, addr: impl Into<IpAddr>) -> Self {
+        self.local_addr = Some(addr.into());
+        self
+    }
+
+    /// Returns a reference to the connection request.
+    pub fn request(&self) -> &R {
+        &self.request
+    }
+
+    /// Returns request hostname.
+    pub fn hostname(&self) -> &str {
+        self.request.hostname()
+    }
+
+    /// Returns request port.
+    pub fn port(&self) -> u16 {
+        self.request.port().unwrap_or(self.port)
+    }
+
+    /// Get borrowed iterator of resolved request addresses.
+    ///
+    /// # Examples
+    /// ```
+    /// # use std::net::SocketAddr;
+    /// # use actix_tls::connect::ConnectInfo;
+    /// let addr = SocketAddr::from(([127, 0, 0, 1], 4242));
+    ///
+    /// let conn = ConnectInfo::new("localhost");
+    /// let mut addrs = conn.addrs();
+    /// assert!(addrs.next().is_none());
+    ///
+    /// let conn = ConnectInfo::with_addr("localhost", addr);
+    /// let mut addrs = conn.addrs();
+    /// assert_eq!(addrs.next().unwrap(), addr);
+    /// ```
+    #[allow(clippy::implied_bounds_in_impls)]
+    pub fn addrs(
+        &self,
+    ) -> impl Iterator<Item = SocketAddr>
+           + ExactSizeIterator
+           + iter::FusedIterator
+           + Clone
+           + fmt::Debug
+           + '_ {
+        match self.addr {
+            ConnectAddrs::None => ConnectAddrsIter::None,
+            ConnectAddrs::One(addr) => ConnectAddrsIter::One(addr),
+            ConnectAddrs::Multi(ref addrs) => ConnectAddrsIter::Multi(addrs.iter()),
+        }
+    }
+
+    /// Take owned iterator resolved request addresses.
+    ///
+    /// # Examples
+    /// ```
+    /// # use std::net::SocketAddr;
+    /// # use actix_tls::connect::ConnectInfo;
+    /// let addr = SocketAddr::from(([127, 0, 0, 1], 4242));
+    ///
+    /// let mut conn = ConnectInfo::new("localhost");
+    /// let mut addrs = conn.take_addrs();
+    /// assert!(addrs.next().is_none());
+    ///
+    /// let mut conn = ConnectInfo::with_addr("localhost", addr);
+    /// let mut addrs = conn.take_addrs();
+    /// assert_eq!(addrs.next().unwrap(), addr);
+    /// ```
+    #[allow(clippy::implied_bounds_in_impls)]
+    pub fn take_addrs(
+        &mut self,
+    ) -> impl Iterator<Item = SocketAddr>
+           + ExactSizeIterator
+           + iter::FusedIterator
+           + Clone
+           + fmt::Debug
+           + 'static {
+        match mem::take(&mut self.addr) {
+            ConnectAddrs::None => ConnectAddrsIter::None,
+            ConnectAddrs::One(addr) => ConnectAddrsIter::One(addr),
+            ConnectAddrs::Multi(addrs) => ConnectAddrsIter::MultiOwned(addrs.into_iter()),
+        }
+    }
+}
+
+impl<R: Host> From<R> for ConnectInfo<R> {
+    fn from(addr: R) -> Self {
+        ConnectInfo::new(addr)
+    }
+}
+
+impl<R: Host> fmt::Display for ConnectInfo<R> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}:{}", self.hostname(), self.port())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::net::Ipv4Addr;
+
+    use super::*;
+
+    #[test]
+    fn test_addr_iter_multi() {
+        let localhost = SocketAddr::from((IpAddr::from(Ipv4Addr::LOCALHOST), 8080));
+        let unspecified = SocketAddr::from((IpAddr::from(Ipv4Addr::UNSPECIFIED), 8080));
+
+        let mut addrs = VecDeque::new();
+        addrs.push_back(localhost);
+        addrs.push_back(unspecified);
+
+        let mut iter = ConnectAddrsIter::Multi(addrs.iter());
+        assert_eq!(iter.next(), Some(localhost));
+        assert_eq!(iter.next(), Some(unspecified));
+        assert_eq!(iter.next(), None);
+
+        let mut iter = ConnectAddrsIter::MultiOwned(addrs.into_iter());
+        assert_eq!(iter.next(), Some(localhost));
+        assert_eq!(iter.next(), Some(unspecified));
+        assert_eq!(iter.next(), None);
+    }
+
+    #[test]
+    fn test_addr_iter_single() {
+        let localhost = SocketAddr::from((IpAddr::from(Ipv4Addr::LOCALHOST), 8080));
+
+        let mut iter = ConnectAddrsIter::One(localhost);
+        assert_eq!(iter.next(), Some(localhost));
+        assert_eq!(iter.next(), None);
+
+        let mut iter = ConnectAddrsIter::None;
+        assert_eq!(iter.next(), None);
+    }
+
+    #[test]
+    fn test_local_addr() {
+        let conn = ConnectInfo::new("hello").set_local_addr([127, 0, 0, 1]);
+        assert_eq!(
+            conn.local_addr.unwrap(),
+            IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))
+        )
+    }
+
+    #[test]
+    fn request_ref() {
+        let conn = ConnectInfo::new("hello");
+        assert_eq!(conn.request(), &"hello")
+    }
+
+    #[test]
+    fn set_connect_addr_into_option() {
+        let addr = SocketAddr::from(([127, 0, 0, 1], 4242));
+
+        let conn = ConnectInfo::new("hello").set_addr(None);
+        let mut addrs = conn.addrs();
+        assert!(addrs.next().is_none());
+
+        let conn = ConnectInfo::new("hello").set_addr(addr);
+        let mut addrs = conn.addrs();
+        assert_eq!(addrs.next().unwrap(), addr);
+
+        let conn = ConnectInfo::new("hello").set_addr(Some(addr));
+        let mut addrs = conn.addrs();
+        assert_eq!(addrs.next().unwrap(), addr);
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/mod.rs.html b/src/actix_tls/connect/mod.rs.html new file mode 100644 index 00000000..fdc674be --- /dev/null +++ b/src/actix_tls/connect/mod.rs.html @@ -0,0 +1,133 @@ +mod.rs - source

actix_tls/connect/
mod.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
//! TCP and TLS connector services.
+//!
+//! # Stages of the TCP connector service:
+//! 1. Resolve [`Host`] (if needed) with given [`Resolver`] and collect list of socket addresses.
+//! 1. Establish TCP connection and return [`TcpStream`].
+//!
+//! # Stages of TLS connector services:
+//! 1. Resolve DNS and establish a [`TcpStream`] with the TCP connector service.
+//! 1. Wrap the stream and perform connect handshake with remote peer.
+//! 1. Return wrapped stream type that implements `AsyncRead` and `AsyncWrite`.
+//!
+//! [`TcpStream`]: actix_rt::net::TcpStream
+
+mod connect_addrs;
+mod connection;
+mod connector;
+mod error;
+mod host;
+mod info;
+mod resolve;
+mod resolver;
+pub mod tcp;
+
+#[cfg(feature = "uri")]
+mod uri;
+
+#[cfg(feature = "openssl")]
+pub mod openssl;
+
+#[cfg(any(
+    feature = "rustls-0_20-webpki-roots",
+    feature = "rustls-0_20-native-roots",
+))]
+pub mod rustls_0_20;
+
+#[doc(hidden)]
+#[cfg(any(
+    feature = "rustls-0_20-webpki-roots",
+    feature = "rustls-0_20-native-roots",
+))]
+pub use rustls_0_20 as rustls;
+
+#[cfg(any(
+    feature = "rustls-0_21-webpki-roots",
+    feature = "rustls-0_21-native-roots",
+))]
+pub mod rustls_0_21;
+
+#[cfg(feature = "rustls-0_22")]
+pub mod rustls_0_22;
+
+#[cfg(feature = "rustls-0_23")]
+pub mod rustls_0_23;
+
+#[cfg(feature = "native-tls")]
+pub mod native_tls;
+
+pub use self::{
+    connection::Connection,
+    connector::{Connector, ConnectorService},
+    error::ConnectError,
+    host::Host,
+    info::ConnectInfo,
+    resolve::Resolve,
+    resolver::{Resolver, ResolverService},
+};
+
\ No newline at end of file diff --git a/src/actix_tls/connect/native_tls.rs.html b/src/actix_tls/connect/native_tls.rs.html new file mode 100644 index 00000000..08657047 --- /dev/null +++ b/src/actix_tls/connect/native_tls.rs.html @@ -0,0 +1,181 @@ +native_tls.rs - source

actix_tls/connect/
native_tls.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
//! Native-TLS based connector service.
+//!
+//! See [`TlsConnector`] for main connector service factory docs.
+
+use std::io;
+
+use actix_rt::net::ActixStream;
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::future::LocalBoxFuture;
+use tokio_native_tls::{
+    native_tls::TlsConnector as NativeTlsConnector, TlsConnector as AsyncNativeTlsConnector,
+    TlsStream as AsyncTlsStream,
+};
+use tracing::trace;
+
+use crate::connect::{Connection, Host};
+
+pub mod reexports {
+    //! Re-exports from `native-tls` and `tokio-native-tls` that are useful for connectors.
+
+    pub use tokio_native_tls::{native_tls::TlsConnector, TlsStream as AsyncTlsStream};
+}
+
+/// Connector service and factory using `native-tls`.
+#[derive(Clone)]
+pub struct TlsConnector {
+    connector: AsyncNativeTlsConnector,
+}
+
+impl TlsConnector {
+    /// Constructs new connector service from a `native-tls` connector.
+    ///
+    /// This type is it's own service factory, so it can be used in that setting, too.
+    pub fn new(connector: NativeTlsConnector) -> Self {
+        Self {
+            connector: AsyncNativeTlsConnector::from(connector),
+        }
+    }
+}
+
+impl<R: Host, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
+where
+    IO: ActixStream + 'static,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Config = ();
+    type Service = Self;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(self.clone())
+    }
+}
+
+/// The `native-tls` connector is both it's ServiceFactory and Service impl type.
+/// As the factory and service share the same type and state.
+impl<R, IO> Service<Connection<R, IO>> for TlsConnector
+where
+    R: Host,
+    IO: ActixStream + 'static,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, stream: Connection<R, IO>) -> Self::Future {
+        let (io, stream) = stream.replace_io(());
+        let connector = self.connector.clone();
+
+        Box::pin(async move {
+            trace!("TLS handshake start for: {:?}", stream.hostname());
+            connector
+                .connect(stream.hostname(), io)
+                .await
+                .map(|res| {
+                    trace!("TLS handshake success: {:?}", stream.hostname());
+                    stream.replace_io(res).1
+                })
+                .map_err(|e| {
+                    trace!("TLS handshake error: {:?}", e);
+                    io::Error::new(io::ErrorKind::Other, format!("{}", e))
+                })
+        })
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/openssl.rs.html b/src/actix_tls/connect/openssl.rs.html new file mode 100644 index 00000000..2ad5885c --- /dev/null +++ b/src/actix_tls/connect/openssl.rs.html @@ -0,0 +1,303 @@ +openssl.rs - source

actix_tls/connect/
openssl.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
//! OpenSSL based connector service.
+//!
+//! See [`TlsConnector`] for main connector service factory docs.
+
+use std::{
+    future::Future,
+    io,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use actix_rt::net::ActixStream;
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::ready;
+use openssl::ssl::SslConnector;
+use tokio_openssl::SslStream as AsyncSslStream;
+use tracing::trace;
+
+use crate::connect::{Connection, Host};
+
+pub mod reexports {
+    //! Re-exports from `openssl` and `tokio-openssl` that are useful for connectors.
+
+    pub use openssl::ssl::{Error, HandshakeError, SslConnector, SslConnectorBuilder, SslMethod};
+    pub use tokio_openssl::SslStream as AsyncSslStream;
+}
+
+/// Connector service factory using `openssl`.
+pub struct TlsConnector {
+    connector: SslConnector,
+}
+
+impl TlsConnector {
+    /// Constructs new connector service factory from an `openssl` connector.
+    pub fn new(connector: SslConnector) -> Self {
+        TlsConnector { connector }
+    }
+
+    /// Constructs new connector service from an `openssl` connector.
+    pub fn service(connector: SslConnector) -> TlsConnectorService {
+        TlsConnectorService { connector }
+    }
+}
+
+impl Clone for TlsConnector {
+    fn clone(&self) -> Self {
+        Self {
+            connector: self.connector.clone(),
+        }
+    }
+}
+
+impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
+where
+    R: Host,
+    IO: ActixStream + 'static,
+{
+    type Response = Connection<R, AsyncSslStream<IO>>;
+    type Error = io::Error;
+    type Config = ();
+    type Service = TlsConnectorService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(TlsConnectorService {
+            connector: self.connector.clone(),
+        })
+    }
+}
+
+/// Connector service using `openssl`.
+pub struct TlsConnectorService {
+    connector: SslConnector,
+}
+
+impl Clone for TlsConnectorService {
+    fn clone(&self) -> Self {
+        Self {
+            connector: self.connector.clone(),
+        }
+    }
+}
+
+impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Response = Connection<R, AsyncSslStream<IO>>;
+    type Error = io::Error;
+    type Future = ConnectFut<R, IO>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, stream: Connection<R, IO>) -> Self::Future {
+        trace!("TLS handshake start for: {:?}", stream.hostname());
+
+        let (io, stream) = stream.replace_io(());
+        let host = stream.hostname();
+
+        let config = self
+            .connector
+            .configure()
+            .expect("SSL connect configuration was invalid.");
+
+        let ssl = config
+            .into_ssl(host)
+            .expect("SSL connect configuration was invalid.");
+
+        ConnectFut {
+            io: Some(AsyncSslStream::new(ssl, io).unwrap()),
+            stream: Some(stream),
+        }
+    }
+}
+
+/// Connect future for OpenSSL service.
+#[doc(hidden)]
+pub struct ConnectFut<R, IO> {
+    io: Option<AsyncSslStream<IO>>,
+    stream: Option<Connection<R, ()>>,
+}
+
+impl<R: Host, IO> Future for ConnectFut<R, IO>
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Output = Result<Connection<R, AsyncSslStream<IO>>, io::Error>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        let this = self.get_mut();
+
+        match ready!(Pin::new(this.io.as_mut().unwrap()).poll_connect(cx)) {
+            Ok(_) => {
+                let stream = this.stream.take().unwrap();
+                trace!("TLS handshake success: {:?}", stream.hostname());
+                Poll::Ready(Ok(stream.replace_io(this.io.take().unwrap()).1))
+            }
+            Err(err) => {
+                trace!("TLS handshake error: {:?}", err);
+                Poll::Ready(Err(io::Error::new(
+                    io::ErrorKind::Other,
+                    format!("{}", err),
+                )))
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/resolve.rs.html b/src/actix_tls/connect/resolve.rs.html new file mode 100644 index 00000000..dcf531ef --- /dev/null +++ b/src/actix_tls/connect/resolve.rs.html @@ -0,0 +1,125 @@ +resolve.rs - source

actix_tls/connect/
resolve.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
//! The [`Resolve`] trait.
+
+use std::{error::Error as StdError, net::SocketAddr};
+
+use futures_core::future::LocalBoxFuture;
+
+/// Custom async DNS resolvers.
+///
+/// # Examples
+/// ```
+/// use std::net::SocketAddr;
+///
+/// use actix_tls::connect::{Resolve, Resolver};
+/// use futures_util::future::LocalBoxFuture;
+///
+/// // use trust-dns async tokio resolver
+/// use trust_dns_resolver::TokioAsyncResolver;
+///
+/// struct MyResolver {
+///     trust_dns: TokioAsyncResolver,
+/// };
+///
+/// // impl Resolve trait and convert given host address str and port to SocketAddr.
+/// impl Resolve for MyResolver {
+///     fn lookup<'a>(
+///         &'a self,
+///         host: &'a str,
+///         port: u16,
+///     ) -> LocalBoxFuture<'a, Result<Vec<SocketAddr>, Box<dyn std::error::Error>>> {
+///         Box::pin(async move {
+///             let res = self
+///                 .trust_dns
+///                 .lookup_ip(host)
+///                 .await?
+///                 .iter()
+///                 .map(|ip| SocketAddr::new(ip, port))
+///                 .collect();
+///             Ok(res)
+///         })
+///     }
+/// }
+///
+/// let my_resolver = MyResolver {
+///     trust_dns: TokioAsyncResolver::tokio_from_system_conf().unwrap(),
+/// };
+///
+/// // wrap custom resolver
+/// let resolver = Resolver::custom(my_resolver);
+///
+/// // resolver can be passed to connector factory where returned service factory
+/// // can be used to construct new connector services for use in clients
+/// let factory = actix_tls::connect::Connector::new(resolver);
+/// let connector = factory.service();
+/// ```
+pub trait Resolve {
+    /// Given DNS lookup information, returns a future that completes with socket information.
+    fn lookup<'a>(
+        &'a self,
+        host: &'a str,
+        port: u16,
+    ) -> LocalBoxFuture<'a, Result<Vec<SocketAddr>, Box<dyn StdError>>>;
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/resolver.rs.html b/src/actix_tls/connect/resolver.rs.html new file mode 100644 index 00000000..59b9ff3b --- /dev/null +++ b/src/actix_tls/connect/resolver.rs.html @@ -0,0 +1,403 @@ +resolver.rs - source

actix_tls/connect/
resolver.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
use std::{
+    future::Future,
+    io,
+    net::SocketAddr,
+    pin::Pin,
+    rc::Rc,
+    task::{Context, Poll},
+    vec::IntoIter,
+};
+
+use actix_rt::task::{spawn_blocking, JoinHandle};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::{future::LocalBoxFuture, ready};
+use tracing::trace;
+
+use super::{ConnectError, ConnectInfo, Host, Resolve};
+
+/// DNS resolver service factory.
+#[derive(Clone, Default)]
+pub struct Resolver {
+    resolver: ResolverService,
+}
+
+impl Resolver {
+    /// Constructs a new resolver factory with a custom resolver.
+    pub fn custom(resolver: impl Resolve + 'static) -> Self {
+        Self {
+            resolver: ResolverService::custom(resolver),
+        }
+    }
+
+    /// Returns a new resolver service.
+    pub fn service(&self) -> ResolverService {
+        self.resolver.clone()
+    }
+}
+
+impl<R: Host> ServiceFactory<ConnectInfo<R>> for Resolver {
+    type Response = ConnectInfo<R>;
+    type Error = ConnectError;
+    type Config = ();
+    type Service = ResolverService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(self.resolver.clone())
+    }
+}
+
+#[derive(Clone)]
+enum ResolverKind {
+    /// Built-in DNS resolver.
+    ///
+    /// See [`std::net::ToSocketAddrs`] trait.
+    Default,
+
+    /// Custom, user-provided DNS resolver.
+    Custom(Rc<dyn Resolve>),
+}
+
+impl Default for ResolverKind {
+    fn default() -> Self {
+        Self::Default
+    }
+}
+
+/// DNS resolver service.
+#[derive(Clone, Default)]
+pub struct ResolverService {
+    kind: ResolverKind,
+}
+
+impl ResolverService {
+    /// Constructor for custom Resolve trait object and use it as resolver.
+    pub fn custom(resolver: impl Resolve + 'static) -> Self {
+        Self {
+            kind: ResolverKind::Custom(Rc::new(resolver)),
+        }
+    }
+
+    /// Resolve DNS with default resolver.
+    fn default_lookup<R: Host>(
+        req: &ConnectInfo<R>,
+    ) -> JoinHandle<io::Result<IntoIter<SocketAddr>>> {
+        // reconstruct host; concatenate hostname and port together
+        let host = format!("{}:{}", req.hostname(), req.port());
+
+        // run blocking DNS lookup in thread pool since DNS lookups can take upwards of seconds on
+        // some platforms if conditions are poor and OS-level cache is not populated
+        spawn_blocking(move || std::net::ToSocketAddrs::to_socket_addrs(&host))
+    }
+}
+
+impl<R: Host> Service<ConnectInfo<R>> for ResolverService {
+    type Response = ConnectInfo<R>;
+    type Error = ConnectError;
+    type Future = ResolverFut<R>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, req: ConnectInfo<R>) -> Self::Future {
+        if req.addr.is_resolved() {
+            // socket address(es) already resolved; return existing connection request
+            ResolverFut::Resolved(Some(req))
+        } else if let Ok(ip) = req.hostname().parse() {
+            // request hostname is valid ip address; add address to request and return
+            let addr = SocketAddr::new(ip, req.port());
+            let req = req.set_addr(Some(addr));
+            ResolverFut::Resolved(Some(req))
+        } else {
+            trace!("DNS resolver: resolving host {:?}", req.hostname());
+
+            match &self.kind {
+                ResolverKind::Default => {
+                    let fut = Self::default_lookup(&req);
+                    ResolverFut::LookUp(fut, Some(req))
+                }
+
+                ResolverKind::Custom(resolver) => {
+                    let resolver = Rc::clone(resolver);
+
+                    ResolverFut::LookupCustom(Box::pin(async move {
+                        let addrs = resolver
+                            .lookup(req.hostname(), req.port())
+                            .await
+                            .map_err(ConnectError::Resolver)?;
+
+                        let req = req.set_addrs(addrs);
+
+                        if req.addr.is_unresolved() {
+                            Err(ConnectError::NoRecords)
+                        } else {
+                            Ok(req)
+                        }
+                    }))
+                }
+            }
+        }
+    }
+}
+
+/// Future for resolver service.
+#[doc(hidden)]
+pub enum ResolverFut<R: Host> {
+    Resolved(Option<ConnectInfo<R>>),
+    LookUp(
+        JoinHandle<io::Result<IntoIter<SocketAddr>>>,
+        Option<ConnectInfo<R>>,
+    ),
+    LookupCustom(LocalBoxFuture<'static, Result<ConnectInfo<R>, ConnectError>>),
+}
+
+impl<R: Host> Future for ResolverFut<R> {
+    type Output = Result<ConnectInfo<R>, ConnectError>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.get_mut() {
+            Self::Resolved(conn) => Poll::Ready(Ok(conn
+                .take()
+                .expect("ResolverFuture polled after finished"))),
+
+            Self::LookUp(fut, req) => {
+                let res = match ready!(Pin::new(fut).poll(cx)) {
+                    Ok(Ok(res)) => Ok(res),
+                    Ok(Err(err)) => Err(ConnectError::Resolver(Box::new(err))),
+                    Err(err) => Err(ConnectError::Io(err.into())),
+                };
+
+                let req = req.take().unwrap();
+
+                let addrs = res.map_err(|err| {
+                    trace!(
+                        "DNS resolver: failed to resolve host {:?} err: {:?}",
+                        req.hostname(),
+                        err
+                    );
+
+                    err
+                })?;
+
+                let req = req.set_addrs(addrs);
+
+                trace!(
+                    "DNS resolver: host {:?} resolved to {:?}",
+                    req.hostname(),
+                    req.addrs()
+                );
+
+                if req.addr.is_unresolved() {
+                    Poll::Ready(Err(ConnectError::NoRecords))
+                } else {
+                    Poll::Ready(Ok(req))
+                }
+            }
+
+            Self::LookupCustom(fut) => fut.as_mut().poll(cx),
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/rustls_0_20.rs.html b/src/actix_tls/connect/rustls_0_20.rs.html new file mode 100644 index 00000000..87b20a29 --- /dev/null +++ b/src/actix_tls/connect/rustls_0_20.rs.html @@ -0,0 +1,359 @@ +rustls_0_20.rs - source

actix_tls/connect/
rustls_0_20.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
//! Rustls based connector service.
+//!
+//! See [`TlsConnector`] for main connector service factory docs.
+
+use std::{
+    future::Future,
+    io,
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+};
+
+use actix_rt::net::ActixStream;
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::ready;
+use tokio_rustls::{
+    client::TlsStream as AsyncTlsStream,
+    rustls::{client::ServerName, ClientConfig, RootCertStore},
+    Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
+};
+use tokio_rustls_023 as tokio_rustls;
+
+use crate::connect::{Connection, Host};
+
+pub mod reexports {
+    //! Re-exports from the `rustls` v0.20 ecosystem that are useful for connectors.
+
+    pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
+    #[cfg(feature = "rustls-0_20-webpki-roots")]
+    pub use webpki_roots_022::TLS_SERVER_ROOTS;
+}
+
+/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
+///
+/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
+///
+/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_06::load_native_certs()
+#[cfg(feature = "rustls-0_20-native-roots")]
+pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
+    let mut root_certs = RootCertStore::empty();
+
+    for cert in rustls_native_certs_06::load_native_certs()? {
+        root_certs
+            .add(&tokio_rustls_023::rustls::Certificate(cert.0))
+            .unwrap();
+    }
+
+    Ok(root_certs)
+}
+
+/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
+#[cfg(feature = "rustls-0_20-webpki-roots")]
+pub fn webpki_roots_cert_store() -> RootCertStore {
+    use tokio_rustls_023::rustls;
+
+    let mut root_certs = RootCertStore::empty();
+
+    for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
+        let cert = rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
+            cert.subject,
+            cert.spki,
+            cert.name_constraints,
+        );
+        let certs = vec![cert].into_iter();
+        root_certs.add_server_trust_anchors(certs);
+    }
+
+    root_certs
+}
+
+/// Connector service factory using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnector {
+    connector: Arc<ClientConfig>,
+}
+
+impl TlsConnector {
+    /// Constructs new connector service factory from a `rustls` client configuration.
+    pub fn new(connector: Arc<ClientConfig>) -> Self {
+        TlsConnector { connector }
+    }
+
+    /// Constructs new connector service from a `rustls` client configuration.
+    pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
+        TlsConnectorService { connector }
+    }
+}
+
+impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
+where
+    R: Host,
+    IO: ActixStream + 'static,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Config = ();
+    type Service = TlsConnectorService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(TlsConnectorService {
+            connector: self.connector.clone(),
+        })
+    }
+}
+
+/// Connector service using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnectorService {
+    connector: Arc<ClientConfig>,
+}
+
+impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Future = ConnectFut<R, IO>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, connection: Connection<R, IO>) -> Self::Future {
+        tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
+        let (stream, connection) = connection.replace_io(());
+
+        match ServerName::try_from(connection.hostname()) {
+            Ok(host) => ConnectFut::Future {
+                connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
+                    .connect(host, stream),
+                connection: Some(connection),
+            },
+            Err(_) => ConnectFut::InvalidDns,
+        }
+    }
+}
+
+/// Connect future for Rustls service.
+#[doc(hidden)]
+#[allow(clippy::large_enum_variant)]
+pub enum ConnectFut<R, IO> {
+    /// See issue <https://github.com/briansmith/webpki/issues/54>
+    InvalidDns,
+    Future {
+        connect: RustlsConnect<IO>,
+        connection: Option<Connection<R, ()>>,
+    },
+}
+
+impl<R, IO> Future for ConnectFut<R, IO>
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.get_mut() {
+            Self::InvalidDns => Poll::Ready(Err(io::Error::new(
+                io::ErrorKind::Other,
+                "Rustls v0.20 can only handle hostname-based connections. Enable the `rustls-0_21` \
+                feature and use the Rustls v0.21 utilities to gain this feature.",
+            ))),
+
+            Self::Future {
+                connect,
+                connection,
+            } => {
+                let stream = ready!(Pin::new(connect).poll(cx))?;
+                let connection = connection.take().unwrap();
+                tracing::trace!("TLS handshake success: {:?}", connection.hostname());
+                Poll::Ready(Ok(connection.replace_io(stream).1))
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/rustls_0_21.rs.html b/src/actix_tls/connect/rustls_0_21.rs.html new file mode 100644 index 00000000..05949d10 --- /dev/null +++ b/src/actix_tls/connect/rustls_0_21.rs.html @@ -0,0 +1,355 @@ +rustls_0_21.rs - source

actix_tls/connect/
rustls_0_21.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
//! Rustls based connector service.
+//!
+//! See [`TlsConnector`] for main connector service factory docs.
+
+use std::{
+    future::Future,
+    io,
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+};
+
+use actix_rt::net::ActixStream;
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::ready;
+use tokio_rustls::{
+    client::TlsStream as AsyncTlsStream,
+    rustls::{client::ServerName, ClientConfig, RootCertStore},
+    Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
+};
+use tokio_rustls_024 as tokio_rustls;
+
+use crate::connect::{Connection, Host};
+
+pub mod reexports {
+    //! Re-exports from the `rustls` v0.21 ecosystem that are useful for connectors.
+
+    pub use tokio_rustls_024::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
+    #[cfg(feature = "rustls-0_21-webpki-roots")]
+    pub use webpki_roots_025::TLS_SERVER_ROOTS;
+}
+
+/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
+///
+/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
+///
+/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_06::load_native_certs()
+#[cfg(feature = "rustls-0_21-native-roots")]
+pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
+    let mut root_certs = RootCertStore::empty();
+
+    for cert in rustls_native_certs_06::load_native_certs()? {
+        root_certs
+            .add(&tokio_rustls_024::rustls::Certificate(cert.0))
+            .unwrap();
+    }
+
+    Ok(root_certs)
+}
+
+/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
+#[cfg(feature = "rustls-0_21-webpki-roots")]
+pub fn webpki_roots_cert_store() -> RootCertStore {
+    use tokio_rustls_024::rustls;
+
+    let mut root_certs = RootCertStore::empty();
+
+    for cert in webpki_roots_025::TLS_SERVER_ROOTS {
+        let cert = rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
+            cert.subject,
+            cert.spki,
+            cert.name_constraints,
+        );
+        let certs = vec![cert].into_iter();
+        root_certs.add_trust_anchors(certs);
+    }
+
+    root_certs
+}
+
+/// Connector service factory using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnector {
+    connector: Arc<ClientConfig>,
+}
+
+impl TlsConnector {
+    /// Constructs new connector service factory from a `rustls` client configuration.
+    pub fn new(connector: Arc<ClientConfig>) -> Self {
+        TlsConnector { connector }
+    }
+
+    /// Constructs new connector service from a `rustls` client configuration.
+    pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
+        TlsConnectorService { connector }
+    }
+}
+
+impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
+where
+    R: Host,
+    IO: ActixStream + 'static,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Config = ();
+    type Service = TlsConnectorService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(TlsConnectorService {
+            connector: self.connector.clone(),
+        })
+    }
+}
+
+/// Connector service using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnectorService {
+    connector: Arc<ClientConfig>,
+}
+
+impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Future = ConnectFut<R, IO>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, connection: Connection<R, IO>) -> Self::Future {
+        tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
+        let (stream, connection) = connection.replace_io(());
+
+        match ServerName::try_from(connection.hostname()) {
+            Ok(host) => ConnectFut::Future {
+                connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
+                    .connect(host, stream),
+                connection: Some(connection),
+            },
+            Err(_) => ConnectFut::InvalidServerName,
+        }
+    }
+}
+
+/// Connect future for Rustls service.
+#[doc(hidden)]
+#[allow(clippy::large_enum_variant)]
+pub enum ConnectFut<R, IO> {
+    InvalidServerName,
+    Future {
+        connect: RustlsConnect<IO>,
+        connection: Option<Connection<R, ()>>,
+    },
+}
+
+impl<R, IO> Future for ConnectFut<R, IO>
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.get_mut() {
+            Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
+                io::ErrorKind::InvalidInput,
+                "connection parameters specified invalid server name",
+            ))),
+
+            Self::Future {
+                connect,
+                connection,
+            } => {
+                let stream = ready!(Pin::new(connect).poll(cx))?;
+                let connection = connection.take().unwrap();
+                tracing::trace!("TLS handshake success: {:?}", connection.hostname());
+                Poll::Ready(Ok(connection.replace_io(stream).1))
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/rustls_0_22.rs.html b/src/actix_tls/connect/rustls_0_22.rs.html new file mode 100644 index 00000000..c65f1ff8 --- /dev/null +++ b/src/actix_tls/connect/rustls_0_22.rs.html @@ -0,0 +1,327 @@ +rustls_0_22.rs - source

actix_tls/connect/
rustls_0_22.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
//! Rustls based connector service.
+//!
+//! See [`TlsConnector`] for main connector service factory docs.
+
+use std::{
+    future::Future,
+    io,
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+};
+
+use actix_rt::net::ActixStream;
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::ready;
+use rustls_pki_types_1::ServerName;
+use tokio_rustls::{
+    client::TlsStream as AsyncTlsStream, rustls::ClientConfig, Connect as RustlsConnect,
+    TlsConnector as RustlsTlsConnector,
+};
+use tokio_rustls_025 as tokio_rustls;
+
+use crate::connect::{Connection, Host};
+
+pub mod reexports {
+    //! Re-exports from the `rustls` v0.22 ecosystem that are useful for connectors.
+
+    pub use tokio_rustls_025::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
+    #[cfg(feature = "rustls-0_22-webpki-roots")]
+    pub use webpki_roots_026::TLS_SERVER_ROOTS;
+}
+
+/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
+///
+/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
+///
+/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_07::load_native_certs()
+#[cfg(feature = "rustls-0_22-native-roots")]
+pub fn native_roots_cert_store() -> io::Result<tokio_rustls::rustls::RootCertStore> {
+    let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
+
+    for cert in rustls_native_certs_07::load_native_certs()? {
+        root_certs.add(cert).unwrap();
+    }
+
+    Ok(root_certs)
+}
+
+/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
+#[cfg(feature = "rustls-0_22-webpki-roots")]
+pub fn webpki_roots_cert_store() -> tokio_rustls::rustls::RootCertStore {
+    let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
+    root_certs.extend(webpki_roots_026::TLS_SERVER_ROOTS.to_owned());
+    root_certs
+}
+
+/// Connector service factory using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnector {
+    connector: Arc<ClientConfig>,
+}
+
+impl TlsConnector {
+    /// Constructs new connector service factory from a `rustls` client configuration.
+    pub fn new(connector: Arc<ClientConfig>) -> Self {
+        TlsConnector { connector }
+    }
+
+    /// Constructs new connector service from a `rustls` client configuration.
+    pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
+        TlsConnectorService { connector }
+    }
+}
+
+impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
+where
+    R: Host,
+    IO: ActixStream + 'static,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Config = ();
+    type Service = TlsConnectorService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(TlsConnectorService {
+            connector: self.connector.clone(),
+        })
+    }
+}
+
+/// Connector service using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnectorService {
+    connector: Arc<ClientConfig>,
+}
+
+impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Future = ConnectFut<R, IO>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, connection: Connection<R, IO>) -> Self::Future {
+        tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
+        let (stream, conn) = connection.replace_io(());
+
+        match ServerName::try_from(conn.hostname()) {
+            Ok(host) => ConnectFut::Future {
+                connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
+                    .connect(host.to_owned(), stream),
+                connection: Some(conn),
+            },
+            Err(_) => ConnectFut::InvalidServerName,
+        }
+    }
+}
+
+/// Connect future for Rustls service.
+#[doc(hidden)]
+#[allow(clippy::large_enum_variant)]
+pub enum ConnectFut<R, IO> {
+    InvalidServerName,
+    Future {
+        connect: RustlsConnect<IO>,
+        connection: Option<Connection<R, ()>>,
+    },
+}
+
+impl<R, IO> Future for ConnectFut<R, IO>
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.get_mut() {
+            Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
+                io::ErrorKind::InvalidInput,
+                "connection parameters specified invalid server name",
+            ))),
+
+            Self::Future {
+                connect,
+                connection,
+            } => {
+                let stream = ready!(Pin::new(connect).poll(cx))?;
+                let connection = connection.take().unwrap();
+                tracing::trace!("TLS handshake success: {:?}", connection.hostname());
+                Poll::Ready(Ok(connection.replace_io(stream).1))
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/rustls_0_23.rs.html b/src/actix_tls/connect/rustls_0_23.rs.html new file mode 100644 index 00000000..7ea63499 --- /dev/null +++ b/src/actix_tls/connect/rustls_0_23.rs.html @@ -0,0 +1,327 @@ +rustls_0_23.rs - source

actix_tls/connect/
rustls_0_23.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
//! Rustls based connector service.
+//!
+//! See [`TlsConnector`] for main connector service factory docs.
+
+use std::{
+    future::Future,
+    io,
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll},
+};
+
+use actix_rt::net::ActixStream;
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::ready;
+use rustls_pki_types_1::ServerName;
+use tokio_rustls::{
+    client::TlsStream as AsyncTlsStream, rustls::ClientConfig, Connect as RustlsConnect,
+    TlsConnector as RustlsTlsConnector,
+};
+use tokio_rustls_026 as tokio_rustls;
+
+use crate::connect::{Connection, Host};
+
+pub mod reexports {
+    //! Re-exports from the `rustls` v0.23 ecosystem that are useful for connectors.
+
+    pub use tokio_rustls_026::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
+    #[cfg(feature = "rustls-0_23-webpki-roots")]
+    pub use webpki_roots_026::TLS_SERVER_ROOTS;
+}
+
+/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
+///
+/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
+///
+/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_07::load_native_certs()
+#[cfg(feature = "rustls-0_23-native-roots")]
+pub fn native_roots_cert_store() -> io::Result<tokio_rustls::rustls::RootCertStore> {
+    let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
+
+    for cert in rustls_native_certs_07::load_native_certs()? {
+        root_certs.add(cert).unwrap();
+    }
+
+    Ok(root_certs)
+}
+
+/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
+#[cfg(feature = "rustls-0_23-webpki-roots")]
+pub fn webpki_roots_cert_store() -> tokio_rustls::rustls::RootCertStore {
+    let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
+    root_certs.extend(webpki_roots_026::TLS_SERVER_ROOTS.to_owned());
+    root_certs
+}
+
+/// Connector service factory using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnector {
+    connector: Arc<ClientConfig>,
+}
+
+impl TlsConnector {
+    /// Constructs new connector service factory from a `rustls` client configuration.
+    pub fn new(connector: Arc<ClientConfig>) -> Self {
+        TlsConnector { connector }
+    }
+
+    /// Constructs new connector service from a `rustls` client configuration.
+    pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
+        TlsConnectorService { connector }
+    }
+}
+
+impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
+where
+    R: Host,
+    IO: ActixStream + 'static,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Config = ();
+    type Service = TlsConnectorService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(TlsConnectorService {
+            connector: self.connector.clone(),
+        })
+    }
+}
+
+/// Connector service using `rustls`.
+#[derive(Clone)]
+pub struct TlsConnectorService {
+    connector: Arc<ClientConfig>,
+}
+
+impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Response = Connection<R, AsyncTlsStream<IO>>;
+    type Error = io::Error;
+    type Future = ConnectFut<R, IO>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, connection: Connection<R, IO>) -> Self::Future {
+        tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
+        let (stream, conn) = connection.replace_io(());
+
+        match ServerName::try_from(conn.hostname()) {
+            Ok(host) => ConnectFut::Future {
+                connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
+                    .connect(host.to_owned(), stream),
+                connection: Some(conn),
+            },
+            Err(_) => ConnectFut::InvalidServerName,
+        }
+    }
+}
+
+/// Connect future for Rustls service.
+#[doc(hidden)]
+#[allow(clippy::large_enum_variant)]
+pub enum ConnectFut<R, IO> {
+    InvalidServerName,
+    Future {
+        connect: RustlsConnect<IO>,
+        connection: Option<Connection<R, ()>>,
+    },
+}
+
+impl<R, IO> Future for ConnectFut<R, IO>
+where
+    R: Host,
+    IO: ActixStream,
+{
+    type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.get_mut() {
+            Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
+                io::ErrorKind::InvalidInput,
+                "connection parameters specified invalid server name",
+            ))),
+
+            Self::Future {
+                connect,
+                connection,
+            } => {
+                let stream = ready!(Pin::new(connect).poll(cx))?;
+                let connection = connection.take().unwrap();
+                tracing::trace!("TLS handshake success: {:?}", connection.hostname());
+                Poll::Ready(Ok(connection.replace_io(stream).1))
+            }
+        }
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/tcp.rs.html b/src/actix_tls/connect/tcp.rs.html new file mode 100644 index 00000000..0feffb86 --- /dev/null +++ b/src/actix_tls/connect/tcp.rs.html @@ -0,0 +1,409 @@ +tcp.rs - source

actix_tls/connect/
tcp.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
//! TCP connector service.
+//!
+//! See [`TcpConnector`] for main connector service factory docs.
+
+use std::{
+    collections::VecDeque,
+    future::Future,
+    io,
+    net::{IpAddr, SocketAddr, SocketAddrV4, SocketAddrV6},
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use actix_rt::net::{TcpSocket, TcpStream};
+use actix_service::{Service, ServiceFactory};
+use actix_utils::future::{ok, Ready};
+use futures_core::ready;
+use tokio_util::sync::ReusableBoxFuture;
+use tracing::{error, trace};
+
+use super::{connect_addrs::ConnectAddrs, error::ConnectError, ConnectInfo, Connection, Host};
+
+/// TCP connector service factory.
+#[derive(Debug, Clone, Copy, Default)]
+#[non_exhaustive]
+pub struct TcpConnector;
+
+impl TcpConnector {
+    /// Returns a new TCP connector service.
+    pub fn service(&self) -> TcpConnectorService {
+        TcpConnectorService::default()
+    }
+}
+
+impl<R: Host> ServiceFactory<ConnectInfo<R>> for TcpConnector {
+    type Response = Connection<R, TcpStream>;
+    type Error = ConnectError;
+    type Config = ();
+    type Service = TcpConnectorService;
+    type InitError = ();
+    type Future = Ready<Result<Self::Service, Self::InitError>>;
+
+    fn new_service(&self, _: ()) -> Self::Future {
+        ok(self.service())
+    }
+}
+
+/// TCP connector service.
+#[derive(Debug, Copy, Clone, Default)]
+#[non_exhaustive]
+pub struct TcpConnectorService;
+
+impl<R: Host> Service<ConnectInfo<R>> for TcpConnectorService {
+    type Response = Connection<R, TcpStream>;
+    type Error = ConnectError;
+    type Future = TcpConnectorFut<R>;
+
+    actix_service::always_ready!();
+
+    fn call(&self, req: ConnectInfo<R>) -> Self::Future {
+        let port = req.port();
+
+        let ConnectInfo {
+            request: req,
+            addr,
+            local_addr,
+            ..
+        } = req;
+
+        TcpConnectorFut::new(req, port, local_addr, addr)
+    }
+}
+
+/// Connect future for TCP service.
+#[doc(hidden)]
+pub enum TcpConnectorFut<R> {
+    Response {
+        req: Option<R>,
+        port: u16,
+        local_addr: Option<IpAddr>,
+        addrs: Option<VecDeque<SocketAddr>>,
+        stream: ReusableBoxFuture<'static, Result<TcpStream, io::Error>>,
+    },
+
+    Error(Option<ConnectError>),
+}
+
+impl<R: Host> TcpConnectorFut<R> {
+    pub(crate) fn new(
+        req: R,
+        port: u16,
+        local_addr: Option<IpAddr>,
+        addr: ConnectAddrs,
+    ) -> TcpConnectorFut<R> {
+        if addr.is_unresolved() {
+            error!("TCP connector: unresolved connection address");
+            return TcpConnectorFut::Error(Some(ConnectError::Unresolved));
+        }
+
+        trace!(
+            "TCP connector: connecting to {} on port {}",
+            req.hostname(),
+            port
+        );
+
+        match addr {
+            ConnectAddrs::None => unreachable!("none variant already checked"),
+
+            ConnectAddrs::One(addr) => TcpConnectorFut::Response {
+                req: Some(req),
+                port,
+                local_addr,
+                addrs: None,
+                stream: ReusableBoxFuture::new(connect(addr, local_addr)),
+            },
+
+            // When resolver returns multiple socket addr for request they would be popped from
+            // front end of queue and returns with the first successful TCP connection.
+            ConnectAddrs::Multi(mut addrs) => {
+                let addr = addrs.pop_front().unwrap();
+
+                TcpConnectorFut::Response {
+                    req: Some(req),
+                    port,
+                    local_addr,
+                    addrs: Some(addrs),
+                    stream: ReusableBoxFuture::new(connect(addr, local_addr)),
+                }
+            }
+        }
+    }
+}
+
+impl<R: Host> Future for TcpConnectorFut<R> {
+    type Output = Result<Connection<R, TcpStream>, ConnectError>;
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.get_mut() {
+            TcpConnectorFut::Error(err) => Poll::Ready(Err(err.take().unwrap())),
+
+            TcpConnectorFut::Response {
+                req,
+                port,
+                local_addr,
+                addrs,
+                stream,
+            } => loop {
+                match ready!(stream.poll(cx)) {
+                    Ok(sock) => {
+                        let req = req.take().unwrap();
+
+                        trace!(
+                            "TCP connector: successfully connected to {:?} - {:?}",
+                            req.hostname(),
+                            sock.peer_addr()
+                        );
+
+                        return Poll::Ready(Ok(Connection::new(req, sock)));
+                    }
+
+                    Err(err) => {
+                        trace!(
+                            "TCP connector: failed to connect to {:?} port: {}",
+                            req.as_ref().unwrap().hostname(),
+                            port,
+                        );
+
+                        if let Some(addr) = addrs.as_mut().and_then(|addrs| addrs.pop_front()) {
+                            stream.set(connect(addr, *local_addr));
+                        } else {
+                            return Poll::Ready(Err(ConnectError::Io(err)));
+                        }
+                    }
+                }
+            },
+        }
+    }
+}
+
+async fn connect(addr: SocketAddr, local_addr: Option<IpAddr>) -> io::Result<TcpStream> {
+    // use local addr if connect asks for it
+    match local_addr {
+        Some(ip_addr) => {
+            let socket = match ip_addr {
+                IpAddr::V4(ip_addr) => {
+                    let socket = TcpSocket::new_v4()?;
+                    let addr = SocketAddr::V4(SocketAddrV4::new(ip_addr, 0));
+                    socket.bind(addr)?;
+                    socket
+                }
+                IpAddr::V6(ip_addr) => {
+                    let socket = TcpSocket::new_v6()?;
+                    let addr = SocketAddr::V6(SocketAddrV6::new(ip_addr, 0, 0, 0));
+                    socket.bind(addr)?;
+                    socket
+                }
+            };
+
+            socket.connect(addr).await
+        }
+
+        None => TcpStream::connect(addr).await,
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/connect/uri.rs.html b/src/actix_tls/connect/uri.rs.html new file mode 100644 index 00000000..23297dab --- /dev/null +++ b/src/actix_tls/connect/uri.rs.html @@ -0,0 +1,127 @@ +uri.rs - source

actix_tls/connect/
uri.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
use super::Host;
+
+impl Host for http_0_2::Uri {
+    fn hostname(&self) -> &str {
+        self.host().unwrap_or("")
+    }
+
+    fn port(&self) -> Option<u16> {
+        match self.port_u16() {
+            Some(port) => Some(port),
+            None => scheme_to_port(self.scheme_str()),
+        }
+    }
+}
+
+impl Host for http_1::Uri {
+    fn hostname(&self) -> &str {
+        self.host().unwrap_or("")
+    }
+
+    fn port(&self) -> Option<u16> {
+        match self.port_u16() {
+            Some(port) => Some(port),
+            None => scheme_to_port(self.scheme_str()),
+        }
+    }
+}
+
+// Get port from well-known URL schemes.
+fn scheme_to_port(scheme: Option<&str>) -> Option<u16> {
+    match scheme {
+        // HTTP
+        Some("http") => Some(80),
+        Some("https") => Some(443),
+
+        // WebSockets
+        Some("ws") => Some(80),
+        Some("wss") => Some(443),
+
+        // Advanced Message Queuing Protocol (AMQP)
+        Some("amqp") => Some(5672),
+        Some("amqps") => Some(5671),
+
+        // Message Queuing Telemetry Transport (MQTT)
+        Some("mqtt") => Some(1883),
+        Some("mqtts") => Some(8883),
+
+        // File Transfer Protocol (FTP)
+        Some("ftp") => Some(21),
+        Some("ftps") => Some(990),
+
+        // Redis
+        Some("redis") => Some(6379),
+
+        // MySQL
+        Some("mysql") => Some(3306),
+
+        // PostgreSQL
+        Some("postgres") => Some(5432),
+
+        _ => None,
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_tls/lib.rs.html b/src/actix_tls/lib.rs.html new file mode 100644 index 00000000..9991dc8a --- /dev/null +++ b/src/actix_tls/lib.rs.html @@ -0,0 +1,35 @@ +lib.rs - source

actix_tls/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
//! TLS acceptor and connector services for the Actix ecosystem.
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+
+#[cfg(feature = "openssl")]
+#[allow(unused_extern_crates)]
+extern crate tls_openssl as openssl;
+
+#[cfg(feature = "accept")]
+pub mod accept;
+
+#[cfg(feature = "connect")]
+pub mod connect;
+
\ No newline at end of file diff --git a/src/actix_tracing/lib.rs.html b/src/actix_tracing/lib.rs.html new file mode 100644 index 00000000..b5717635 --- /dev/null +++ b/src/actix_tracing/lib.rs.html @@ -0,0 +1,511 @@ +lib.rs - source

actix_tracing/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
//! Actix tracing - support for tokio tracing with Actix services.
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
+use core::marker::PhantomData;
+
+use actix_service::{
+    apply, ApplyTransform, IntoServiceFactory, Service, ServiceFactory, Transform,
+};
+use actix_utils::future::{ok, Either, Ready};
+use tracing_futures::{Instrument, Instrumented};
+
+/// A `Service` implementation that automatically enters/exits tracing spans
+/// for the wrapped inner service.
+#[derive(Clone)]
+pub struct TracingService<S, F> {
+    inner: S,
+    make_span: F,
+}
+
+impl<S, F> TracingService<S, F> {
+    pub fn new(inner: S, make_span: F) -> Self {
+        TracingService { inner, make_span }
+    }
+}
+
+impl<S, Req, F> Service<Req> for TracingService<S, F>
+where
+    S: Service<Req>,
+    F: Fn(&Req) -> Option<tracing::Span>,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Future = Either<S::Future, Instrumented<S::Future>>;
+
+    actix_service::forward_ready!(inner);
+
+    fn call(&self, req: Req) -> Self::Future {
+        let span = (self.make_span)(&req);
+        let _enter = span.as_ref().map(|s| s.enter());
+
+        let fut = self.inner.call(req);
+
+        // make a child span to track the future's execution
+        if let Some(span) = span
+            .clone()
+            .map(|span| tracing::span!(parent: &span, tracing::Level::INFO, "future"))
+        {
+            Either::right(fut.instrument(span))
+        } else {
+            Either::left(fut)
+        }
+    }
+}
+
+/// A `Transform` implementation that wraps services with a [`TracingService`].
+pub struct TracingTransform<S, U, F> {
+    make_span: F,
+    _p: PhantomData<fn(S, U)>,
+}
+
+impl<S, U, F> TracingTransform<S, U, F> {
+    pub fn new(make_span: F) -> Self {
+        TracingTransform {
+            make_span,
+            _p: PhantomData,
+        }
+    }
+}
+
+impl<S, Req, U, F> Transform<S, Req> for TracingTransform<S, U, F>
+where
+    S: Service<Req>,
+    U: ServiceFactory<Req, Response = S::Response, Error = S::Error, Service = S>,
+    F: Fn(&Req) -> Option<tracing::Span> + Clone,
+{
+    type Response = S::Response;
+    type Error = S::Error;
+    type Transform = TracingService<S, F>;
+    type InitError = U::InitError;
+    type Future = Ready<Result<Self::Transform, Self::InitError>>;
+
+    fn new_transform(&self, service: S) -> Self::Future {
+        ok(TracingService::new(service, self.make_span.clone()))
+    }
+}
+
+/// Wraps the provided service factory with a transform that automatically
+/// enters/exits the given span.
+///
+/// The span to be entered/exited can be provided via a closure. The closure
+/// is passed in a reference to the request being handled by the service.
+///
+/// For example:
+/// ```ignore
+/// let traced_service = trace(
+///     web_service,
+///     |req: &Request| Some(span!(Level::INFO, "request", req.id))
+/// );
+/// ```
+pub fn trace<S, Req, I, F>(
+    service_factory: I,
+    make_span: F,
+) -> ApplyTransform<TracingTransform<S::Service, S, F>, S, Req>
+where
+    I: IntoServiceFactory<S, Req>,
+    S: ServiceFactory<Req>,
+    F: Fn(&Req) -> Option<tracing::Span> + Clone,
+{
+    apply(
+        TracingTransform::new(make_span),
+        service_factory.into_factory(),
+    )
+}
+
+#[cfg(test)]
+mod test {
+    use std::{
+        cell::RefCell,
+        collections::{BTreeMap, BTreeSet},
+        sync::{Arc, RwLock},
+    };
+
+    use actix_service::{fn_factory, fn_service};
+    use slab::Slab;
+    use tracing::{span, Event, Level, Metadata, Subscriber};
+
+    use super::*;
+
+    thread_local! {
+        static SPAN: RefCell<Vec<span::Id>> = const { RefCell::new(Vec::new()) };
+    }
+
+    #[derive(Default)]
+    struct Stats {
+        entered_spans: BTreeSet<u64>,
+        exited_spans: BTreeSet<u64>,
+        events_count: BTreeMap<u64, usize>,
+    }
+
+    #[derive(Default)]
+    struct Inner {
+        spans: Slab<&'static Metadata<'static>>,
+        stats: Stats,
+    }
+
+    #[derive(Clone, Default)]
+    struct TestSubscriber {
+        inner: Arc<RwLock<Inner>>,
+    }
+
+    impl Subscriber for TestSubscriber {
+        fn enabled(&self, _metadata: &Metadata<'_>) -> bool {
+            true
+        }
+
+        fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
+            let id = self.inner.write().unwrap().spans.insert(span.metadata());
+            span::Id::from_u64(id as u64 + 1)
+        }
+
+        fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
+
+        fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
+
+        fn event(&self, event: &Event<'_>) {
+            let id = event
+                .parent()
+                .cloned()
+                .or_else(|| SPAN.with(|current_span| current_span.borrow().last().cloned()))
+                .unwrap();
+
+            *self
+                .inner
+                .write()
+                .unwrap()
+                .stats
+                .events_count
+                .entry(id.into_u64())
+                .or_insert(0) += 1;
+        }
+
+        fn enter(&self, span: &span::Id) {
+            self.inner
+                .write()
+                .unwrap()
+                .stats
+                .entered_spans
+                .insert(span.into_u64());
+
+            SPAN.with(|current_span| {
+                current_span.borrow_mut().push(span.clone());
+            });
+        }
+
+        fn exit(&self, span: &span::Id) {
+            self.inner
+                .write()
+                .unwrap()
+                .stats
+                .exited_spans
+                .insert(span.into_u64());
+
+            // we are guaranteed that on any given thread, spans are exited in reverse order
+            SPAN.with(|current_span| {
+                let leaving = current_span
+                    .borrow_mut()
+                    .pop()
+                    .expect("told to exit span when not in span");
+                assert_eq!(
+                    &leaving, span,
+                    "told to exit span that was not most recently entered"
+                );
+            });
+        }
+    }
+
+    #[actix_rt::test]
+    async fn service_call() {
+        let service_factory = fn_factory(|| {
+            ok::<_, ()>(fn_service(|req: &'static str| {
+                tracing::event!(Level::TRACE, "It's happening - {}!", req);
+                ok::<_, ()>(())
+            }))
+        });
+
+        let subscriber = TestSubscriber::default();
+        let _guard = tracing::subscriber::set_default(subscriber.clone());
+
+        let span_svc = span!(Level::TRACE, "span_svc");
+        let trace_service_factory = trace(service_factory, |_: &&str| Some(span_svc.clone()));
+        let service = trace_service_factory.new_service(()).await.unwrap();
+        service.call("boo").await.unwrap();
+
+        let id = span_svc.id().unwrap().into_u64();
+        assert!(subscriber
+            .inner
+            .read()
+            .unwrap()
+            .stats
+            .entered_spans
+            .contains(&id));
+        assert!(subscriber
+            .inner
+            .read()
+            .unwrap()
+            .stats
+            .exited_spans
+            .contains(&id));
+        assert_eq!(subscriber.inner.read().unwrap().stats.events_count[&id], 1);
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_utils/counter.rs.html b/src/actix_utils/counter.rs.html new file mode 100644 index 00000000..6d83cf33 --- /dev/null +++ b/src/actix_utils/counter.rs.html @@ -0,0 +1,199 @@ +counter.rs - source

actix_utils/
counter.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
//! Task-notifying counter.
+
+use core::{cell::Cell, fmt, task};
+use std::rc::Rc;
+
+use local_waker::LocalWaker;
+
+/// Simple counter with ability to notify task on reaching specific number
+///
+/// Counter could be cloned, total n-count is shared across all clones.
+#[derive(Debug, Clone)]
+pub struct Counter(Rc<CounterInner>);
+
+impl Counter {
+    /// Create `Counter` instance with max value.
+    pub fn new(capacity: usize) -> Self {
+        Counter(Rc::new(CounterInner {
+            capacity,
+            count: Cell::new(0),
+            task: LocalWaker::new(),
+        }))
+    }
+
+    /// Create new counter guard, incrementing the counter.
+    #[inline]
+    pub fn get(&self) -> CounterGuard {
+        CounterGuard::new(self.0.clone())
+    }
+
+    /// Returns true if counter is below capacity. Otherwise, register to wake task when it is.
+    #[inline]
+    pub fn available(&self, cx: &task::Context<'_>) -> bool {
+        self.0.available(cx)
+    }
+
+    /// Get total number of acquired guards.
+    #[inline]
+    pub fn total(&self) -> usize {
+        self.0.count.get()
+    }
+}
+
+struct CounterInner {
+    count: Cell<usize>,
+    capacity: usize,
+    task: LocalWaker,
+}
+
+impl CounterInner {
+    fn inc(&self) {
+        self.count.set(self.count.get() + 1);
+    }
+
+    fn dec(&self) {
+        let num = self.count.get();
+        self.count.set(num - 1);
+        if num == self.capacity {
+            self.task.wake();
+        }
+    }
+
+    fn available(&self, cx: &task::Context<'_>) -> bool {
+        if self.count.get() < self.capacity {
+            true
+        } else {
+            self.task.register(cx.waker());
+            false
+        }
+    }
+}
+
+impl fmt::Debug for CounterInner {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Counter")
+            .field("count", &self.count.get())
+            .field("capacity", &self.capacity)
+            .field("task", &self.task)
+            .finish()
+    }
+}
+
+/// An RAII structure that keeps the underlying counter incremented until this guard is dropped.
+#[derive(Debug)]
+pub struct CounterGuard(Rc<CounterInner>);
+
+impl CounterGuard {
+    fn new(inner: Rc<CounterInner>) -> Self {
+        inner.inc();
+        CounterGuard(inner)
+    }
+}
+
+impl Unpin for CounterGuard {}
+
+impl Drop for CounterGuard {
+    fn drop(&mut self) {
+        self.0.dec();
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_utils/future/either.rs.html b/src/actix_utils/future/either.rs.html new file mode 100644 index 00000000..9ada25fc --- /dev/null +++ b/src/actix_utils/future/either.rs.html @@ -0,0 +1,191 @@ +either.rs - source

actix_utils/future/
either.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
//! A symmetric either future.
+
+use core::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+use pin_project_lite::pin_project;
+
+pin_project! {
+    /// Combines two different futures that have the same output type.
+    ///
+    /// Construct variants with [`Either::left`] and [`Either::right`].
+    ///
+    /// # Examples
+    /// ```
+    /// use actix_utils::future::{ready, Ready, Either};
+    ///
+    /// # async fn run() {
+    /// let res = Either::<_, Ready<usize>>::left(ready(42));
+    /// assert_eq!(res.await, 42);
+    ///
+    /// let res = Either::<Ready<usize>, _>::right(ready(43));
+    /// assert_eq!(res.await, 43);
+    /// # }
+    /// ```
+    #[project = EitherProj]
+    #[derive(Debug, Clone)]
+    pub enum Either<L, R> {
+        /// A value of type `L`.
+        #[allow(missing_docs)]
+        Left { #[pin] value: L },
+
+        /// A value of type `R`.
+        #[allow(missing_docs)]
+        Right { #[pin] value: R },
+    }
+}
+
+impl<L, R> Either<L, R> {
+    /// Creates new `Either` using left variant.
+    #[inline]
+    pub fn left(value: L) -> Either<L, R> {
+        Either::Left { value }
+    }
+
+    /// Creates new `Either` using right variant.
+    #[inline]
+    pub fn right(value: R) -> Either<L, R> {
+        Either::Right { value }
+    }
+}
+
+impl<T> Either<T, T> {
+    /// Unwraps into inner value when left and right have a common type.
+    #[inline]
+    pub fn into_inner(self) -> T {
+        match self {
+            Either::Left { value } => value,
+            Either::Right { value } => value,
+        }
+    }
+}
+
+impl<L, R> Future for Either<L, R>
+where
+    L: Future,
+    R: Future<Output = L::Output>,
+{
+    type Output = L::Output;
+
+    #[inline]
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.project() {
+            EitherProj::Left { value } => value.poll(cx),
+            EitherProj::Right { value } => value.poll(cx),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::future::{ready, Ready};
+
+    #[actix_rt::test]
+    async fn test_either() {
+        let res = Either::<_, Ready<usize>>::left(ready(42));
+        assert_eq!(res.await, 42);
+
+        let res = Either::<Ready<usize>, _>::right(ready(43));
+        assert_eq!(res.await, 43);
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_utils/future/mod.rs.html b/src/actix_utils/future/mod.rs.html new file mode 100644 index 00000000..c28023e7 --- /dev/null +++ b/src/actix_utils/future/mod.rs.html @@ -0,0 +1,23 @@ +mod.rs - source

actix_utils/future/
mod.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
//! Helpers for constructing futures.
+
+mod either;
+mod poll_fn;
+mod ready;
+
+pub use self::{
+    either::Either,
+    poll_fn::{poll_fn, PollFn},
+    ready::{err, ok, ready, Ready},
+};
+
\ No newline at end of file diff --git a/src/actix_utils/future/poll_fn.rs.html b/src/actix_utils/future/poll_fn.rs.html new file mode 100644 index 00000000..6eb9257b --- /dev/null +++ b/src/actix_utils/future/poll_fn.rs.html @@ -0,0 +1,249 @@ +poll_fn.rs - source

actix_utils/future/
poll_fn.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
//! Simple "poll function" future and factory.
+
+use core::{
+    fmt,
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+/// Creates a future driven by the provided function that receives a task context.
+///
+/// # Examples
+/// ```
+/// # use std::task::Poll;
+/// # use actix_utils::future::poll_fn;
+/// # async fn test_poll_fn() {
+/// let res = poll_fn(|_| Poll::Ready(42)).await;
+/// assert_eq!(res, 42);
+///
+/// let mut i = 5;
+/// let res = poll_fn(|cx| {
+///     i -= 1;
+///
+///     if i > 0 {
+///         cx.waker().wake_by_ref();
+///         Poll::Pending
+///     } else {
+///         Poll::Ready(42)
+///     }
+/// })
+/// .await;
+/// assert_eq!(res, 42);
+/// # }
+/// # actix_rt::Runtime::new().unwrap().block_on(test_poll_fn());
+/// ```
+#[inline]
+pub fn poll_fn<F, T>(f: F) -> PollFn<F>
+where
+    F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+    PollFn { f }
+}
+
+/// Future for the [`poll_fn`] function.
+pub struct PollFn<F> {
+    f: F,
+}
+
+impl<F> fmt::Debug for PollFn<F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("PollFn").finish()
+    }
+}
+
+impl<F, T> Future for PollFn<F>
+where
+    F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+    type Output = T;
+
+    #[inline]
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        // SAFETY: we are not moving out of the pinned field
+        // see https://github.com/rust-lang/rust/pull/102737
+        #[allow(clippy::needless_borrow)]
+        (unsafe { &mut self.get_unchecked_mut().f })(cx)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::marker::PhantomPinned;
+
+    use super::*;
+
+    static_assertions::assert_impl_all!(PollFn<()>: Unpin);
+    static_assertions::assert_not_impl_all!(PollFn<PhantomPinned>: Unpin);
+
+    #[actix_rt::test]
+    async fn test_poll_fn() {
+        let res = poll_fn(|_| Poll::Ready(42)).await;
+        assert_eq!(res, 42);
+
+        let mut i = 5;
+        let res = poll_fn(|cx| {
+            i -= 1;
+
+            if i > 0 {
+                cx.waker().wake_by_ref();
+                Poll::Pending
+            } else {
+                Poll::Ready(42)
+            }
+        })
+        .await;
+        assert_eq!(res, 42);
+    }
+
+    // following soundness tests taken from https://github.com/tokio-rs/tokio/pull/5087
+
+    #[allow(dead_code)]
+    fn require_send<T: Send>(_t: &T) {}
+    #[allow(dead_code)]
+    fn require_sync<T: Sync>(_t: &T) {}
+
+    #[allow(unused)]
+    trait AmbiguousIfUnpin<A> {
+        fn some_item(&self) {}
+    }
+    impl<T: ?Sized> AmbiguousIfUnpin<()> for T {}
+    impl<T: ?Sized + Unpin> AmbiguousIfUnpin<[u8; 0]> for T {}
+
+    const _: fn() = || {
+        let pinned = std::marker::PhantomPinned;
+        let f = poll_fn(move |_| {
+            // Use `pinned` to take ownership of it.
+            let _ = &pinned;
+            std::task::Poll::Pending::<()>
+        });
+        require_send(&f);
+        require_sync(&f);
+        AmbiguousIfUnpin::some_item(&f);
+    };
+}
+
\ No newline at end of file diff --git a/src/actix_utils/future/ready.rs.html b/src/actix_utils/future/ready.rs.html new file mode 100644 index 00000000..412010a7 --- /dev/null +++ b/src/actix_utils/future/ready.rs.html @@ -0,0 +1,265 @@ +ready.rs - source

actix_utils/future/
ready.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
//! When `core::future::Ready` has a `into_inner()` method, this can be deprecated.
+
+use core::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+/// Future for the [`ready`] function.
+///
+/// Panic will occur if polled more than once.
+///
+/// # Examples
+/// ```
+/// use actix_utils::future::ready;
+///
+/// // async
+/// # async fn run() {
+/// let a = ready(1);
+/// assert_eq!(a.await, 1);
+/// # }
+///
+/// // sync
+/// let a = ready(1);
+/// assert_eq!(a.into_inner(), 1);
+/// ```
+#[derive(Debug, Clone)]
+#[must_use = "futures do nothing unless you `.await` or poll them"]
+pub struct Ready<T> {
+    val: Option<T>,
+}
+
+impl<T> Ready<T> {
+    /// Unwraps the value from this immediately ready future.
+    #[inline]
+    pub fn into_inner(mut self) -> T {
+        self.val.take().unwrap()
+    }
+}
+
+impl<T> Unpin for Ready<T> {}
+
+impl<T> Future for Ready<T> {
+    type Output = T;
+
+    #[inline]
+    fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
+        let val = self.val.take().expect("Ready polled after completion");
+        Poll::Ready(val)
+    }
+}
+
+/// Creates a future that is immediately ready with a value.
+///
+/// # Examples
+/// ```no_run
+/// use actix_utils::future::ready;
+///
+/// # async fn run() {
+/// let a = ready(1);
+/// assert_eq!(a.await, 1);
+/// # }
+///
+/// // sync
+/// let a = ready(1);
+/// assert_eq!(a.into_inner(), 1);
+/// ```
+#[inline]
+pub fn ready<T>(val: T) -> Ready<T> {
+    Ready { val: Some(val) }
+}
+
+/// Creates a future that is immediately ready with a success value.
+///
+/// # Examples
+/// ```no_run
+/// use actix_utils::future::ok;
+///
+/// # async fn run() {
+/// let a = ok::<_, ()>(1);
+/// assert_eq!(a.await, Ok(1));
+/// # }
+/// ```
+#[inline]
+pub fn ok<T, E>(val: T) -> Ready<Result<T, E>> {
+    Ready { val: Some(Ok(val)) }
+}
+
+/// Creates a future that is immediately ready with an error value.
+///
+/// # Examples
+/// ```no_run
+/// use actix_utils::future::err;
+///
+/// # async fn run() {
+/// let a = err::<(), _>(1);
+/// assert_eq!(a.await, Err(1));
+/// # }
+/// ```
+#[inline]
+pub fn err<T, E>(err: E) -> Ready<Result<T, E>> {
+    Ready {
+        val: Some(Err(err)),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::rc::Rc;
+
+    use futures_util::task::noop_waker;
+    use static_assertions::{assert_impl_all, assert_not_impl_any};
+
+    use super::*;
+
+    assert_impl_all!(Ready<()>: Send, Sync, Unpin, Clone);
+    assert_impl_all!(Ready<Rc<()>>: Unpin, Clone);
+    assert_not_impl_any!(Ready<Rc<()>>: Send, Sync);
+
+    #[test]
+    #[should_panic]
+    fn multiple_poll_panics() {
+        let waker = noop_waker();
+        let mut cx = Context::from_waker(&waker);
+
+        let mut ready = ready(1);
+        assert_eq!(Pin::new(&mut ready).poll(&mut cx), Poll::Ready(1));
+
+        // panic!
+        let _ = Pin::new(&mut ready).poll(&mut cx);
+    }
+}
+
\ No newline at end of file diff --git a/src/actix_utils/lib.rs.html b/src/actix_utils/lib.rs.html new file mode 100644 index 00000000..59f7d428 --- /dev/null +++ b/src/actix_utils/lib.rs.html @@ -0,0 +1,19 @@ +lib.rs - source

actix_utils/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
//! Various utilities used in the Actix ecosystem.
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
+#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+
+pub mod counter;
+pub mod future;
+
\ No newline at end of file diff --git a/src/bytestring/lib.rs.html b/src/bytestring/lib.rs.html new file mode 100644 index 00000000..863d0199 --- /dev/null +++ b/src/bytestring/lib.rs.html @@ -0,0 +1,937 @@ +lib.rs - source

bytestring/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
//! A UTF-8 encoded read-only string using `Bytes` as storage.
+//!
+//! See docs for [`ByteString`].
+
+#![no_std]
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+
+extern crate alloc;
+
+use alloc::{
+    boxed::Box,
+    string::{String, ToString},
+    vec::Vec,
+};
+use core::{borrow::Borrow, fmt, hash, ops, str};
+
+use bytes::Bytes;
+
+/// An immutable UTF-8 encoded string with [`Bytes`] as a storage.
+#[derive(Clone, Default, Eq, PartialOrd, Ord)]
+pub struct ByteString(Bytes);
+
+impl ByteString {
+    /// Creates a new empty `ByteString`.
+    pub const fn new() -> Self {
+        ByteString(Bytes::new())
+    }
+
+    /// Get a reference to the underlying `Bytes` object.
+    pub fn as_bytes(&self) -> &Bytes {
+        &self.0
+    }
+
+    /// Unwraps this `ByteString` into the underlying `Bytes` object.
+    pub fn into_bytes(self) -> Bytes {
+        self.0
+    }
+
+    /// Creates a new `ByteString` from a `&'static str`.
+    pub const fn from_static(src: &'static str) -> ByteString {
+        Self(Bytes::from_static(src.as_bytes()))
+    }
+
+    /// Creates a new `ByteString` from a Bytes.
+    ///
+    /// # Safety
+    /// This function is unsafe because it does not check the bytes passed to it are valid UTF-8.
+    /// If this constraint is violated, it may cause memory unsafety issues with future users of
+    /// the `ByteString`, as we assume that `ByteString`s are valid UTF-8. However, the most likely
+    /// issue is that the data gets corrupted.
+    pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString {
+        Self(src)
+    }
+
+    /// Returns a new byte string that is equivalent to the given `subset`.
+    ///
+    /// When processing a `ByteString` buffer with other tools, one often gets a `&str` which is in
+    /// fact a slice of the original `ByteString`; i.e., a subset of it. This function turns that
+    /// `&str` into another `ByteString`, as if one had sliced the `ByteString` with the offsets
+    /// that correspond to `subset`.
+    ///
+    /// Corresponds to [`Bytes::slice_ref`].
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `subset` is not a sub-slice of this byte string.
+    ///
+    /// Note that strings which are only subsets from an equality perspective do not uphold this
+    /// requirement; see examples.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use bytestring::ByteString;
+    /// let string = ByteString::from_static(" foo ");
+    /// let subset = string.trim();
+    /// let substring = string.slice_ref(subset);
+    /// assert_eq!(substring, "foo");
+    /// ```
+    ///
+    /// ```should_panic
+    /// # use bytestring::ByteString;
+    /// // panics because the given slice is not derived from the original byte string, despite
+    /// // being a logical subset of the string
+    /// ByteString::from_static("foo bar").slice_ref("foo");
+    /// ```
+    pub fn slice_ref(&self, subset: &str) -> Self {
+        Self(self.0.slice_ref(subset.as_bytes()))
+    }
+}
+
+impl PartialEq<str> for ByteString {
+    fn eq(&self, other: &str) -> bool {
+        &self[..] == other
+    }
+}
+
+impl<T: AsRef<str>> PartialEq<T> for ByteString {
+    fn eq(&self, other: &T) -> bool {
+        &self[..] == other.as_ref()
+    }
+}
+
+impl AsRef<ByteString> for ByteString {
+    fn as_ref(&self) -> &ByteString {
+        self
+    }
+}
+
+impl AsRef<[u8]> for ByteString {
+    fn as_ref(&self) -> &[u8] {
+        self.0.as_ref()
+    }
+}
+
+impl AsRef<str> for ByteString {
+    fn as_ref(&self) -> &str {
+        self
+    }
+}
+
+impl hash::Hash for ByteString {
+    fn hash<H: hash::Hasher>(&self, state: &mut H) {
+        (**self).hash(state);
+    }
+}
+
+impl ops::Deref for ByteString {
+    type Target = str;
+
+    #[inline]
+    fn deref(&self) -> &str {
+        let bytes = self.0.as_ref();
+        // SAFETY: UTF-8 validity is guaranteed during construction.
+        unsafe { str::from_utf8_unchecked(bytes) }
+    }
+}
+
+impl Borrow<str> for ByteString {
+    fn borrow(&self) -> &str {
+        self
+    }
+}
+
+impl From<String> for ByteString {
+    #[inline]
+    fn from(value: String) -> Self {
+        Self(Bytes::from(value))
+    }
+}
+
+impl From<&str> for ByteString {
+    #[inline]
+    fn from(value: &str) -> Self {
+        Self(Bytes::copy_from_slice(value.as_ref()))
+    }
+}
+
+impl From<Box<str>> for ByteString {
+    #[inline]
+    fn from(value: Box<str>) -> Self {
+        Self(Bytes::from(value.into_boxed_bytes()))
+    }
+}
+
+impl From<ByteString> for String {
+    #[inline]
+    fn from(value: ByteString) -> Self {
+        value.to_string()
+    }
+}
+
+impl TryFrom<&[u8]> for ByteString {
+    type Error = str::Utf8Error;
+
+    #[inline]
+    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
+        let _ = str::from_utf8(value)?;
+        Ok(ByteString(Bytes::copy_from_slice(value)))
+    }
+}
+
+impl TryFrom<Vec<u8>> for ByteString {
+    type Error = str::Utf8Error;
+
+    #[inline]
+    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
+        let buf = String::from_utf8(value).map_err(|err| err.utf8_error())?;
+        Ok(ByteString(Bytes::from(buf)))
+    }
+}
+
+impl TryFrom<Bytes> for ByteString {
+    type Error = str::Utf8Error;
+
+    #[inline]
+    fn try_from(value: Bytes) -> Result<Self, Self::Error> {
+        let _ = str::from_utf8(value.as_ref())?;
+        Ok(ByteString(value))
+    }
+}
+
+impl TryFrom<bytes::BytesMut> for ByteString {
+    type Error = str::Utf8Error;
+
+    #[inline]
+    fn try_from(value: bytes::BytesMut) -> Result<Self, Self::Error> {
+        let _ = str::from_utf8(&value)?;
+        Ok(ByteString(value.freeze()))
+    }
+}
+
+macro_rules! array_impls {
+    ($($len:expr)+) => {
+        $(
+            impl TryFrom<[u8; $len]> for ByteString {
+                type Error = str::Utf8Error;
+
+                #[inline]
+                fn try_from(value: [u8; $len]) -> Result<Self, Self::Error> {
+                    ByteString::try_from(&value[..])
+                }
+            }
+
+            impl TryFrom<&[u8; $len]> for ByteString {
+                type Error = str::Utf8Error;
+
+                #[inline]
+                fn try_from(value: &[u8; $len]) -> Result<Self, Self::Error> {
+                    ByteString::try_from(&value[..])
+                }
+            }
+        )+
+    }
+}
+
+array_impls!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32);
+
+impl fmt::Debug for ByteString {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        (**self).fmt(fmt)
+    }
+}
+
+impl fmt::Display for ByteString {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        (**self).fmt(fmt)
+    }
+}
+
+#[cfg(feature = "serde")]
+mod serde {
+    use alloc::string::String;
+
+    use serde::{
+        de::{Deserialize, Deserializer},
+        ser::{Serialize, Serializer},
+    };
+
+    use super::ByteString;
+
+    impl Serialize for ByteString {
+        #[inline]
+        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            serializer.serialize_str(self.as_ref())
+        }
+    }
+
+    impl<'de> Deserialize<'de> for ByteString {
+        #[inline]
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: Deserializer<'de>,
+        {
+            String::deserialize(deserializer).map(ByteString::from)
+        }
+    }
+
+    #[cfg(test)]
+    mod serde_impl_tests {
+        use serde::de::DeserializeOwned;
+        use static_assertions::assert_impl_all;
+
+        use super::*;
+
+        assert_impl_all!(ByteString: Serialize, DeserializeOwned);
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use alloc::{borrow::ToOwned, format, vec};
+    use core::{
+        hash::{Hash, Hasher},
+        panic::{RefUnwindSafe, UnwindSafe},
+    };
+
+    use ahash::AHasher;
+    use static_assertions::assert_impl_all;
+
+    use super::*;
+
+    assert_impl_all!(ByteString: Send, Sync, Unpin, Sized);
+    assert_impl_all!(ByteString: Clone, Default, Eq, PartialOrd, Ord);
+    assert_impl_all!(ByteString: fmt::Debug, fmt::Display);
+    assert_impl_all!(ByteString: UnwindSafe, RefUnwindSafe);
+
+    #[test]
+    fn eq() {
+        let s: ByteString = ByteString::from_static("test");
+        assert_eq!(s, "test");
+        assert_eq!(s, *"test");
+        assert_eq!(s, "test".to_owned());
+    }
+
+    #[test]
+    fn new() {
+        let _: ByteString = ByteString::new();
+    }
+
+    #[test]
+    fn as_bytes() {
+        let buf = ByteString::new();
+        assert!(buf.as_bytes().is_empty());
+
+        let buf = ByteString::from("hello");
+        assert_eq!(buf.as_bytes(), "hello");
+    }
+
+    #[test]
+    fn from_bytes_unchecked() {
+        let buf = unsafe { ByteString::from_bytes_unchecked(Bytes::new()) };
+        assert!(buf.is_empty());
+
+        let buf = unsafe { ByteString::from_bytes_unchecked(Bytes::from("hello")) };
+        assert_eq!(buf, "hello");
+    }
+
+    #[test]
+    fn as_ref() {
+        let buf = ByteString::new();
+
+        let _: &ByteString = buf.as_ref();
+        let _: &[u8] = buf.as_ref();
+    }
+
+    #[test]
+    fn borrow() {
+        let buf = ByteString::new();
+
+        let _: &str = buf.borrow();
+    }
+
+    #[test]
+    fn hash() {
+        let mut hasher1 = AHasher::default();
+        "str".hash(&mut hasher1);
+
+        let mut hasher2 = AHasher::default();
+        let s = ByteString::from_static("str");
+        s.hash(&mut hasher2);
+        assert_eq!(hasher1.finish(), hasher2.finish());
+    }
+
+    #[test]
+    fn from_string() {
+        let s: ByteString = "hello".to_owned().into();
+        assert_eq!(&s, "hello");
+        let t: &str = s.as_ref();
+        assert_eq!(t, "hello");
+    }
+
+    #[test]
+    fn from_str() {
+        let _: ByteString = "str".into();
+        let _: ByteString = "str".to_owned().into_boxed_str().into();
+    }
+
+    #[test]
+    fn to_string() {
+        let buf = ByteString::from("foo");
+        assert_eq!(String::from(buf), "foo");
+    }
+
+    #[test]
+    fn from_static_str() {
+        static _S: ByteString = ByteString::from_static("hello");
+        let _ = ByteString::from_static("str");
+    }
+
+    #[test]
+    fn try_from_slice() {
+        let _ = ByteString::try_from(b"nice bytes").unwrap();
+    }
+
+    #[test]
+    fn try_from_array() {
+        assert_eq!(
+            ByteString::try_from([b'h', b'i']).unwrap(),
+            ByteString::from_static("hi")
+        );
+    }
+
+    #[test]
+    fn try_from_vec() {
+        let _ = ByteString::try_from(vec![b'f', b'o', b'o']).unwrap();
+        ByteString::try_from(vec![0, 159, 146, 150]).unwrap_err();
+    }
+
+    #[test]
+    fn try_from_bytes() {
+        let _ = ByteString::try_from(Bytes::from_static(b"nice bytes")).unwrap();
+    }
+
+    #[test]
+    fn try_from_bytes_mut() {
+        let _ = ByteString::try_from(bytes::BytesMut::from(&b"nice bytes"[..])).unwrap();
+    }
+
+    #[test]
+    fn display() {
+        let buf = ByteString::from("bar");
+        assert_eq!(format!("{buf}"), "bar");
+    }
+
+    #[test]
+    fn debug() {
+        let buf = ByteString::from("baz");
+        assert_eq!(format!("{buf:?}"), r#""baz""#);
+    }
+
+    #[cfg(feature = "serde")]
+    #[test]
+    fn serialize() {
+        let s: ByteString = serde_json::from_str(r#""nice bytes""#).unwrap();
+        assert_eq!(s, "nice bytes");
+    }
+
+    #[cfg(feature = "serde")]
+    #[test]
+    fn deserialize() {
+        let s = serde_json::to_string(&ByteString::from_static("nice bytes")).unwrap();
+        assert_eq!(s, r#""nice bytes""#);
+    }
+
+    #[test]
+    fn slice_ref() {
+        let string = ByteString::from_static(" foo ");
+        let subset = string.trim();
+        // subset is derived from original byte string
+        let substring = string.slice_ref(subset);
+        assert_eq!(substring, "foo");
+    }
+
+    #[test]
+    #[should_panic]
+    fn slice_ref_catches_not_a_subset() {
+        // panics because the given slice is not derived from the original byte string, despite
+        // being a logical subset of the string
+        ByteString::from_static("foo bar").slice_ref("foo");
+    }
+}
+
\ No newline at end of file diff --git a/src/local_channel/lib.rs.html b/src/local_channel/lib.rs.html new file mode 100644 index 00000000..a1c07568 --- /dev/null +++ b/src/local_channel/lib.rs.html @@ -0,0 +1,21 @@ +lib.rs - source

local_channel/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
//! Non-thread-safe channels.
+//!
+//! See docs for [`mpsc::channel()`].
+
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+
+extern crate alloc;
+
+pub mod mpsc;
+
\ No newline at end of file diff --git a/src/local_channel/mpsc.rs.html b/src/local_channel/mpsc.rs.html new file mode 100644 index 00000000..6b40eef6 --- /dev/null +++ b/src/local_channel/mpsc.rs.html @@ -0,0 +1,511 @@ +mpsc.rs - source

local_channel/
mpsc.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
//! A non-thread-safe multi-producer, single-consumer, futures-aware, FIFO queue.
+
+use alloc::{collections::VecDeque, rc::Rc};
+use core::{
+    cell::RefCell,
+    fmt,
+    future::poll_fn,
+    pin::Pin,
+    task::{Context, Poll},
+};
+use std::error::Error;
+
+use futures_core::stream::Stream;
+use futures_sink::Sink;
+use local_waker::LocalWaker;
+
+/// Creates a unbounded in-memory channel with buffered storage.
+///
+/// [Sender]s and [Receiver]s are `!Send`.
+pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
+    let shared = Rc::new(RefCell::new(Shared {
+        has_receiver: true,
+        buffer: VecDeque::new(),
+        blocked_recv: LocalWaker::new(),
+    }));
+
+    let sender = Sender {
+        shared: shared.clone(),
+    };
+
+    let receiver = Receiver { shared };
+
+    (sender, receiver)
+}
+
+#[derive(Debug)]
+struct Shared<T> {
+    buffer: VecDeque<T>,
+    blocked_recv: LocalWaker,
+    has_receiver: bool,
+}
+
+/// The transmission end of a channel.
+///
+/// This is created by the `channel` function.
+#[derive(Debug)]
+pub struct Sender<T> {
+    shared: Rc<RefCell<Shared<T>>>,
+}
+
+impl<T> Unpin for Sender<T> {}
+
+impl<T> Sender<T> {
+    /// Sends the provided message along this channel.
+    pub fn send(&self, item: T) -> Result<(), SendError<T>> {
+        let mut shared = self.shared.borrow_mut();
+
+        if !shared.has_receiver {
+            // receiver was dropped
+            return Err(SendError(item));
+        };
+
+        shared.buffer.push_back(item);
+        shared.blocked_recv.wake();
+
+        Ok(())
+    }
+
+    /// Closes the sender half.
+    ///
+    /// This prevents any further messages from being sent on the channel, by any sender, while
+    /// still enabling the receiver to drain messages that are already buffered.
+    pub fn close(&mut self) {
+        self.shared.borrow_mut().has_receiver = false;
+    }
+}
+
+impl<T> Clone for Sender<T> {
+    fn clone(&self) -> Self {
+        Sender {
+            shared: self.shared.clone(),
+        }
+    }
+}
+
+impl<T> Sink<T> for Sender<T> {
+    type Error = SendError<T>;
+
+    fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        Poll::Ready(Ok(()))
+    }
+
+    fn start_send(self: Pin<&mut Self>, item: T) -> Result<(), SendError<T>> {
+        self.send(item)
+    }
+
+    fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), SendError<T>>> {
+        Poll::Ready(Ok(()))
+    }
+
+    fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        Poll::Ready(Ok(()))
+    }
+}
+
+impl<T> Drop for Sender<T> {
+    fn drop(&mut self) {
+        let count = Rc::strong_count(&self.shared);
+        let shared = self.shared.borrow_mut();
+
+        // check is last sender is about to drop
+        if shared.has_receiver && count == 2 {
+            // Wake up receiver as its stream has ended
+            shared.blocked_recv.wake();
+        }
+    }
+}
+
+/// The receiving end of a channel which implements the `Stream` trait.
+///
+/// This is created by the [`channel`] function.
+#[derive(Debug)]
+pub struct Receiver<T> {
+    shared: Rc<RefCell<Shared<T>>>,
+}
+
+impl<T> Receiver<T> {
+    /// Receive the next value.
+    ///
+    /// Returns `None` if the channel is empty and has been [closed](Sender::close) explicitly or
+    /// when all senders have been dropped and, therefore, no more values can ever be sent though
+    /// this channel.
+    pub async fn recv(&mut self) -> Option<T> {
+        let mut this = Pin::new(self);
+        poll_fn(|cx| this.as_mut().poll_next(cx)).await
+    }
+
+    /// Create an associated [Sender].
+    pub fn sender(&self) -> Sender<T> {
+        Sender {
+            shared: self.shared.clone(),
+        }
+    }
+}
+
+impl<T> Unpin for Receiver<T> {}
+
+impl<T> Stream for Receiver<T> {
+    type Item = T;
+
+    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
+        let mut shared = self.shared.borrow_mut();
+
+        if Rc::strong_count(&self.shared) == 1 {
+            // All senders have been dropped, so drain the buffer and end the stream.
+            return Poll::Ready(shared.buffer.pop_front());
+        }
+
+        if let Some(msg) = shared.buffer.pop_front() {
+            Poll::Ready(Some(msg))
+        } else {
+            shared.blocked_recv.register(cx.waker());
+            Poll::Pending
+        }
+    }
+}
+
+impl<T> Drop for Receiver<T> {
+    fn drop(&mut self) {
+        let mut shared = self.shared.borrow_mut();
+        shared.buffer.clear();
+        shared.has_receiver = false;
+    }
+}
+
+/// Error returned when attempting to send after the channels' [Receiver] is dropped or closed.
+///
+/// Allows access to message that failed to send with [`into_inner`](Self::into_inner).
+pub struct SendError<T>(pub T);
+
+impl<T> SendError<T> {
+    /// Returns the message that was attempted to be sent but failed.
+    pub fn into_inner(self) -> T {
+        self.0
+    }
+}
+
+impl<T> fmt::Debug for SendError<T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple("SendError").field(&"...").finish()
+    }
+}
+
+impl<T> fmt::Display for SendError<T> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "send failed because receiver is gone")
+    }
+}
+
+impl<T> Error for SendError<T> {}
+
+#[cfg(test)]
+mod tests {
+    use futures_util::{future::lazy, StreamExt as _};
+
+    use super::*;
+
+    #[tokio::test]
+    async fn test_mpsc() {
+        let (tx, mut rx) = channel();
+        tx.send("test").unwrap();
+        assert_eq!(rx.next().await.unwrap(), "test");
+
+        let tx2 = tx.clone();
+        tx2.send("test2").unwrap();
+        assert_eq!(rx.next().await.unwrap(), "test2");
+
+        assert_eq!(
+            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
+            Poll::Pending
+        );
+        drop(tx2);
+        assert_eq!(
+            lazy(|cx| Pin::new(&mut rx).poll_next(cx)).await,
+            Poll::Pending
+        );
+        drop(tx);
+        assert_eq!(rx.next().await, None);
+
+        let (tx, rx) = channel();
+        tx.send("test").unwrap();
+        drop(rx);
+        assert!(tx.send("test").is_err());
+
+        let (mut tx, _) = channel();
+        let tx2 = tx.clone();
+        tx.close();
+        assert!(tx.send("test").is_err());
+        assert!(tx2.send("test").is_err());
+    }
+
+    #[tokio::test]
+    async fn test_recv() {
+        let (tx, mut rx) = channel();
+        tx.send("test").unwrap();
+        assert_eq!(rx.recv().await.unwrap(), "test");
+        drop(tx);
+
+        let (tx, mut rx) = channel();
+        tx.send("test").unwrap();
+        assert_eq!(rx.recv().await.unwrap(), "test");
+        drop(tx);
+        assert!(rx.recv().await.is_none());
+    }
+}
+
\ No newline at end of file diff --git a/src/local_waker/lib.rs.html b/src/local_waker/lib.rs.html new file mode 100644 index 00000000..ce44a295 --- /dev/null +++ b/src/local_waker/lib.rs.html @@ -0,0 +1,147 @@ +lib.rs - source

local_waker/
lib.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
//! A synchronization primitive for thread-local task wakeup.
+//!
+//! See docs for [`LocalWaker`].
+
+#![no_std]
+#![deny(rust_2018_idioms, nonstandard_style)]
+#![warn(future_incompatible, missing_docs)]
+
+use core::{cell::Cell, fmt, marker::PhantomData, task::Waker};
+
+/// A synchronization primitive for task wakeup.
+///
+/// Sometimes the task interested in a given event will change over time. A `LocalWaker` can
+/// coordinate concurrent notifications with the consumer, potentially "updating" the underlying
+/// task to wake up. This is useful in scenarios where a computation completes in another task and
+/// wants to notify the consumer, but the consumer is in the process of being migrated to a new
+/// logical task.
+///
+/// Consumers should call [`register`] before checking the result of a computation and producers
+/// should call [`wake`] after producing the computation (this differs from the usual `thread::park`
+/// pattern). It is also permitted for [`wake`] to be called _before_ [`register`]. This results in
+/// a no-op.
+///
+/// A single `LocalWaker` may be reused for any number of calls to [`register`] or [`wake`].
+///
+/// [`register`]: LocalWaker::register
+/// [`wake`]: LocalWaker::wake
+#[derive(Default)]
+pub struct LocalWaker {
+    pub(crate) waker: Cell<Option<Waker>>,
+    // mark LocalWaker as a !Send type.
+    _phantom: PhantomData<*const ()>,
+}
+
+impl LocalWaker {
+    /// Creates a new, empty `LocalWaker`.
+    pub fn new() -> Self {
+        LocalWaker::default()
+    }
+
+    /// Registers the waker to be notified on calls to `wake`.
+    ///
+    /// Returns `true` if waker was registered before.
+    #[inline]
+    pub fn register(&self, waker: &Waker) -> bool {
+        let last_waker = self.waker.replace(Some(waker.clone()));
+        last_waker.is_some()
+    }
+
+    /// Calls `wake` on the last `Waker` passed to `register`.
+    ///
+    /// If `register` has not been called yet, then this does nothing.
+    #[inline]
+    pub fn wake(&self) {
+        if let Some(waker) = self.take() {
+            waker.wake();
+        }
+    }
+
+    /// Returns the last `Waker` passed to `register`, so that the user can wake it.
+    ///
+    /// If a waker has not been registered, this returns `None`.
+    #[inline]
+    pub fn take(&self) -> Option<Waker> {
+        self.waker.take()
+    }
+}
+
+impl fmt::Debug for LocalWaker {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "LocalWaker")
+    }
+}
+
\ No newline at end of file diff --git a/static.files/COPYRIGHT-23e9bde6c69aea69.txt b/static.files/COPYRIGHT-23e9bde6c69aea69.txt new file mode 100644 index 00000000..1447df79 --- /dev/null +++ b/static.files/COPYRIGHT-23e9bde6c69aea69.txt @@ -0,0 +1,50 @@ +# REUSE-IgnoreStart + +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.ttf.woff2, + SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, + SourceSerif4-It.ttf.woff2): + + Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name + 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United + States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerif4-LICENSE.md. + +This copyright file is intended to be distributed with rustdoc output. + +# REUSE-IgnoreEnd diff --git a/static.files/FiraSans-LICENSE-db4b642586e02d97.txt b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt new file mode 100644 index 00000000..d7e9c149 --- /dev/null +++ b/static.files/FiraSans-LICENSE-db4b642586e02d97.txt @@ -0,0 +1,98 @@ +// REUSE-IgnoreStart + +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 b/static.files/FiraSans-Medium-8f9a781e4970d388.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..7a1e5fc548ef28137a32150b6aa50a568cd53d02 GIT binary patch literal 132780 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�|o|A<_G9#bJ&K$mXTSM@kZfZ^-ZYS)6EG~kHJ{! z(kRY3IK1DAx+i!~-GutTX%UU&{*cBJ60OyuDMC-6c|BUX_5xbdibLNw!xz$XgeJ82 zN%Cl?y$c=cSf_${vuqI@GPZbZRsaEZIN*G!$s-1QE(HoDVGrPgUjxwKMEHad!iXSR zi9LE8;*gJ`JLE=B!ginT9`>n66sM%WB2W<|m=Ei@&UYzk)C8`tBD2&vdNkH_nABd6 zp)as+PT5g-cg+r1KKwc>U&kG9{{3BxHQ$A`F|4Z~q{*@!e-k#kCfAIAbb<9l>LLA*WaIQX z(oh0`-~$4jxea3BsX;BG4*2<&4i%+&-=S7EIaD9&J!)LCSYsA7)^WGvdD3y{K77LG z5q^XaK@5pnDu6TVd8;L$!Zm83Rp>;yZ{&E`Bllk&VuxepDdl;7?Go!Su#B3`3M{as z1tYU_g_AWgN87V0!d>|}WSEJAHR{QQed-4VOwa<`^}{T}LU5@xnNSc}oUm?rBTJyB z*bHXh>98XMJ~exxaM5Gfx5^O9?rM@o{a8;K(-d7vDU3Ofak}*21x$U12firwcZpwM zg^hKwn&mB&ct*7n=#4tlBB81iohxYGQz{W-^zMbdcPU^x2omZ(+Q~cosYg_KRL3YL z7N_O3@I>$Ih6Ovm$nIHAnGuRXSZY?i2+x4GH=}oJJ#=BEDB_%?bRjobG)4a}85@2V zPYtJ&-{o3$AZ>Zzchlw!?G5W^vnZ%ttr6A_xIRK*;&I=!UbB{Vf14S9FIt$%2ApJ1 zV_Wh#Tq478`cre1VP{3c8F2q+q{V?7z!6MvFyed)(CvSdx$z?$!BH8e2LBkYIDc?r z#Gg|212qz6SmDT`YHl&!y|`aPSdF+fHj(}d#PIJzk;p=ks%7TTJdrS^gjWvXtgOx^ zy!Mgkk1VGXynz-v(*F_fQy5k`;^T@WbhtdHNAUULaP2h91OHy}^e2u?xwMPpvs-ED zvy_o#ldYVW4`Q;nBgvSLak@>$w#tPOxR3UHr?emz2nAx|>n&MUg-z}k4=&ZDj;XXXGvs@K zVOjqDRswmnfK2lkv!Yvlnp6|Sb^fq))??vW#`|_xTlL%T|$K-wt6Vo(}9S`>f5;xSFiVdrttr8Nhq5$1mtb_TeGG1-jPv*YXp}sjU-v z$6yO=%$0;Z6bEshhGAVgI+1-o-5FH-`)h-vza4GIBj%b{m}{bqG0mFV+d+0TUGBhB zPjJvK^K99fIrUQ7uH>-r^AlF(@+!skuuNdrr?=iM2va#uk{py~yU8BW4ze3Ap9#)NHdvM; zeh_aaXyV?SgoSoxSlK#X?H8T6Nlo0miCdiy`RLAFrn{v$u3h75)2hwTnp$epSIkgZ z3F;U16T*s)vf{_Y2RWZWytUKN_5`uRh90eNh;Hp>mGqLZOkGPjY`y&=V#n<-ciC#t z+_!lZ9|YlB&9Jt2hTXyb5{r#D4yyyDi_z3uG&r$svbr6|=Rmpxez#9p!I=~s;*b}x zc*@?Y_&zI1S;>i|m_Uh9RNS_elbTmR>vFcjImVvg8i8X?q-0R`H>tUQ>($4StVgi7 zK`8sA+$5AxZgJc;R1a0TZCm<$j@63Z`X-Rnz*?rnM3lefE?ubEoFW0Q< zZEUQ4@uS?_n|hxNgWK&)LyBr*yhHd%<%FYkv+% zZ-CG6W>4KYw0zOx+TvoI;Li~ISw6tIR%h!p0kij1a9kE^R{kM>6}!zw%(@Dg|C}F% z40aC0zsMl3)>sfy_=9R31e7|BQbJVtLms11Xy@`qiX)BX?;``a_!uH4`yX6`n**VN z?}8k^P6=BN>aJl&Df#Cs@{OLa`&7*TNO=Q6Wc-bP*9LNdt3T5aL@B!{1L|J!Xvi~V zFL;8>F+U3C{OFDR5Dko7zb}VJ%;Zqs84}(Ay%ovZ0Ea+$zmNhq1{xAkB07wy6dm-K zGX!e7O8Zf1dPWsQm~TZGCrc7=T{qi$gEv%R=m4-+|5_*5{KwhEW-;0Zmw_LJd7s2& zAiQ6<3e$=WXu>AjJ~N76-c7=G5$W&EIQJ=>AG*X?yO*Ts$d2EDDnHV&5!5%WGVtrH ztp{nJAld&&{xY1#4T65IML9^SEyap6y4)Jh@gh>uAEAchfcZikZ=sQsV z;utI#_!A=7De_8TjL-0e|E@#AvYzrG&z@;=YloK zNrii{e{uDgMPFm#I{4qf7<_%F8?O)x=h@0+l&rfvn&e$$R}g?jApZ9`Go* z4mnDA>FbPUCuI3A;GUq0?0@dKi`WcC{!<&yfuvow-8T&bLGC<({mg)-9#@`nP2#!BgE1T9-`NHhM0yxX_k+=;7i^9eVk23MMPl615 zThiN_lXW|CB#qvgmV@inLLqzgMM)-)-Gu?7c=Q*wpKBp zPA)n~a^N#A8+P?91Zsz5fas@X@gx`7xxLI$y?_}Gvaug(5}Ux}`84DKfr9?Uk@IL2 zT>6UFjDhBtMUF!ea~yEU`L(a+6P0f228OT=GkP{8rHS^K1Xbv*tEYl z;Z+i%rhG;Q6)(@F=M`R<;iDxQx4AU(cn1Lci!r>}K>!3dV+w$%rOZrG2=}1?dhe04 ziF|DsF^L5sM&>?s`z15RE+a;UQH1IJU*ErS#BSX&3UYF2C1CUT1O6bx@Fyhf+w(u^H_~)xxSRk0E%hcNx5{wy4Dt4wzl>v z`^~Q?#z`U0+ACZ88y3*>emp{B@Fu)lq*Ql1O+2C2sklEq%({%!1 zcKA_8xR@+Id3wbZzsZiKKjI{pVFX00vU{*+wa#z7Z&xOFS?Ctk^(-i(TGvzCwWd%t zzv3K5X0KpI+uyVQbo|Lqhau+1_Ey{WMmz1coFh|yd5AQpsinDSx8sg!@4GyBlnq9G zeixBVwSfaQXW!jriHPuS+Sj$`zt1(x3>f|E@Pjf$|4gHKbeSFY20zD!7OG zkp&qtR+2F#^Q&f?_VPnU1^u|A+Z|tTg9eJv)nC)xgYxi~Dh_vNJX#$}NwWz79A5>P zbhcsXq)BTU(ezr!Depoovs}|do8|YmdjLky9oDLd5^#JU4geozREvlAd4z#SXnS;Z zI2!zJaEeUGuoTnr=M(!my^%;JKw$ji!u(@3s~M^Y@E!SGn*9)V!z}6OUYiuV1-lf3 zx8MW#EDqB4H}Dhu7yc-T-1Aag>1v1AY5VDpW)@r~_|7 zGcjK9ns09_Ko5aF68`cYB0e1F2b(%U*MaLz;#( zUHc^L3Gx0?A6=m*^n<~2`A1?LreFrWybp*+``b2pn?pgMvds!&9VAn?7UatT}S$&0na<4q_ky zQXm8Jpad$Qh8foVOX<(KUE6XvNHlsaB#ND}XdN~IGV$7yJw(g7f*(&*8aza-y&W;>@0Pv5VFhhV4pE)$W*<^O#8G8U`@$xq4N(gq#nLi$| zF1}&8vHP^`cPr}nKr+~%2B$LBucHF5MM(xzOM$DqLxCgn_29)hn@lDYc=(-4__FY2 z`n6X+J@s`?AMdkQ2OksqTEhhOp!+@An_LnA&%rArc0GU}k@*k;?jQIPVsw8yYI=k1eieybNE|$2YI=!${ zuDIES8YW(1E-7bNyZs<`$zAMK!0=EMJ^p>^gz!Brx8f=s8|gOmVCq`UfJXY!N%#nT z|B`t4Ntzx7`kB3R9LSjR#vZyEiGx8eY8to%NP-klOAIe^{w%f2)YZLV0fMYI4MuQ4 zewad2*)-QuHT`wcMArv#TVILW`J>Nwg~5i|W{5HN8EJ~cCRpWJQ^>`KHu(4uJA6o^ zu7{37BL9|>8S5$_Ue`+&gW+a3M=lOK-B71}1Lo3IkkQAiP{=Tf#}%Kl2_&deZlOwk zsM>qgjfUnHe&h2M@iN2BIS0_fRB*^sqo&S?jyV$^{;Y&CJF(>)q||dVGOd7xV@15F zD_5v|6)IJ)UTx}{G-z3~PTlJe$a0Sj>F$ZeR(l3Uu8S@Un_zL95~-Wh8G~5dAtK2L zKgUWa<{`ZJJA=}}QFBIxnmam6wvA;eY@hgW?3~ny?4C>lpH5|5_D(z4KYf7%o8AI% zx0ofLw!Bq7Z+#myZfiej-tV$Z`~Gg1jvefft{v}$o}KSMeY-lyRkgM7R&VQ1i2Hq< zF!v|nkh{N|cqrUqsppz|z{NxDzKKld?{Vsp{*0gLkiP|A(vkaC$5H$?ag=T|hkZZi zsNAa@)n_tcbmK?XN@^&bEw&8$vJFg|+s&k{gJAZj$I!>?3iM6MH7uAGteDQXSvk)I zTeZ-IJ7DR{aPYD`w8Qpl&CXrl7TmB!SMu#o%G0@-TZ?`IXrIaobhtAlG( zdxyY2OF($X*NDh2rXse_H-PwVZWQU=NkBG8aH!>E2|HvcIHAM94;KkxlvHG~;v$cq z0Cl1)(I!oWE=^i2=`&%=UJb51_qvj|0Kd^4wGs8C=8v-GhegfXL7+qu&0sW{EmoVu z#ls7z>3y!uuw<%BfYE8iR^3Jd0hjIKKvR3n9DE`pw6X*_b6iI9#>8Yn{#aXs0&%F1 zYQ(V`)sC}us23L+&>*gd7LA}~Q)tz)s&%XV(Wbv0=+Rlb_3gqG0j%HCC9I5;TCr=C zRKXr0Sh80_(zJKl**Pu8TwRlUf?ImfL$~&*thqh!eBF_M0q*W`A?_`#Xb%=soX1Nj z)l;P%fqM}8oXB^Uv2Ehs>~Wx{ zNQqv^WZ5e@m43nEdh^nH_mzeI`+5C;!4C61b;AD5U}_z$+AvGnOvY`~bh4bRn@_fr zLo3N~g6-rqIkS_ThrQ%du%BEfw+@o~1jos<`%k@+w@_b_FVxp$o>r-XvCZR*E~Nhzsm>G>{zL}H0l zX3m^=q$3~YsG$%M37K52E}O8=ueoqBEhH1rIN1j6U)^Gk|Oc$(9m z<2;vt1y^(>SEa72&ge5})(X~t)S;zQUy{2B$^YJu&+RNP>h^Mfd>by7E1aZwQTBuI zE7_3DYnF-=BtHjC&#|;_+h)uBO1@`wP5NG&e?-6? zDsbHSdkf=TDl77!2$v5dk21QL)15$~6O*_kC$)jSNSES=`I)d}3Hb(l%P%B)_ty^Q zXWkwjt!n#m9a6=-qltkhPGO}~7Z2hS<2c1mmvF+=b1J35wtcW})!XFoqY0REdoHFa z>!kK>i2<6k(FAd52|e~yGta&B$m;>;`5;zF{vV;^<4BydbmDlg<>!m(nDQ^SpRdMy zzCF<9FVExuX7*10W>ZUc%TCnImd}AYddC~<00e;{(OBY9#2|;Vxjep5B$n8(sk9#{ zY~6Z$oDPB)30rphX4s6LUQ5q|b?DT^uU}J3TUXz}(8$Ep%>4LeIxzHzWfmA5;n-xv zLCHEPPl;>fhwQ<-cH|yDn5aE-SQRS@%}%l8 z$03d)D2kF>Q;c#1D1RMG1uBw-O4MShqplppYssNCy(>f;Z8@~lo}vS743VG{(?W1+ zX@=5l##LH*Xokt$_sEHf{DqE)h#-49avJ1d zE^4^u;IA?WdjSzS<>?V0=@CO!Gdr-goPtrfr96`skx4>6Nhv5RRi%)cJN|fY%68V$ zwkcsx!m$>zII*=W94xvaQL601atSKQiz?NXjJ`={4MC%poX$z2i=Exp8fxEE?>gne zNzV91G@)0QV)yrDR>3M*p>@bgrr)GHw%odt>g}ZZoejlyQQJ?E?v-eNst+V*D$#Tb z9Zi|fQsmfLF9HOBtpWf50001hJLxeJ*<83#<|2!i!DOo}YOrC?mbvDp5OX^mb0@61 z7rwb4A@hJcA6jJ=hsb1hH#lbpSn~oqk5Qfo#{5T`CIrm?!MIGAT;&GH>=G5MYdVqc z&yj%ZSrC^5i$419=$((_zQ3!jZ{WKPcFVQiBAe^8vSLDm0ssJ81sG%{dj!GR4agob zy8)SGi)2&ly3)&(Cf8$d$W2TWM{t(t>J&+^p*?1-Bj~IP2N-S`-Sp6mq^qB;2?# z64bj53w#gwK@A;)TbKgU*4f37dX~|>*VS-vpp)>Dgod;@j4oAZ23BUs(5m0VJ(QMx z5Bj0UL;rp1Ip~34kXJ=MA}T@W?X_YoV&z$|Lxt!Y*f(|w;<1p{dzoS8uEmnHf@uxw z_BpaUJYyxG`LGZsXp`T9N+r50NSi}w{7r8W+q#sI-oJ)TB>Z3R8v-K})sw~ZG>86~PeP7{K~P+`o3PgpS#$viC+8(H$boyX7Mfk|k7n25n7)yv%f_%O9}odzgY z4CuEeO-2wS23n?0lhwpS124yfLB!oDvRvnRIPI9QAz|WyA+FBtLeMHB2LI-6+MOYGT2t)5{DEJ{vQ4 zx8*K9Q+;)FZPDbbGDCNMQBYx9G_creNyZ=h_4%UA7jrkUYAUOh)h&bdXdA@WM%W~- znkOz=Ym>DXXC130(|440BlU~#J(2asg6V_(V$}@51>)z>#KppTZb!oDXhYc|94$+l zIcczDmbS{%6+tdmVL4qLYR#<05&u0v-x61Ta)Yni65E|77R|0y3uaFfN1tZ8IM5)Q z$~8Y!=+|eZvJ+y}oQ<#NB0C=!7Y0k_Qq0aTz$@TYv23nIcAa6lk>(xo`7Vq1!29Ch z%a}G_Q#3kB@*)ewpG{r7Fv~p^7?LuTtP=mQp;&U>{Guok|5ERqCn->E)tst892-cF zRBsmIAl;u@4?NeSEHN$|H_XjDJ1feeM1^~jjCLPhQOxx$GP{rJ;^suH8It zTT9ZOdV$~5)OT#$NjTa`WY5~O%V)#l8Y{=T5tg8Qagp0CC6~&*r||80{r$Ur^QC=j z-+4p-ZU46`#JewI72tjuV6LAYqXvSE%vgN0av%*Cv*sOX8Xh{3R6 zmxM%7$&-$1p3JJZr#`Cc$%#IT_C>uGeJT26v6jlLD(>WAC*Pogr@lmk5|lDzS1e_y z8WuH}H3D_Q@fzX6uuQ5s#Z|QLX3=r0&&(pB{lq8B{Y4c$$JMHW7qqr}ykq@)ENlPz z=9*eQPA6n0^Vk{SU)|M_xo&H z*Y#X-6#+2 zuR4s!nK&z zJW&G-%@)9+tvw)APPxGHeYjJzM@QC8jM9c5@xn#UjREfl^{Kl-L(mgZxcTQsHokN6 z302d%SHZfLcrihG*t&I=bpYMs8)1dGKL(j$v?v zC`q#I>jqXgCexhtOp)aT_{icL-?i6hI4sdxGTE7sN`TBP^aeeh2{*UlPfBrdT8!o#vPhHQ zZqb|G5%DI@K)8_PN5!Dr3g@ui;9>|%2xMB|mw=~wn$>nsnmUGUAwJEUIYsc5yqF)f z57ZZ&53mD3P(65Fz#IbCRX#(I83M~&IEVw`z;7Tocw4|$sAbk*Y5+D?e%idNLt58P zw7Q^6kHoPow$F;4ImOtqpQ4>oMn5s)84LExhxvBAQ;nITZth0sMkE71K^}2nr^%d* zHh~&Y8-g#9r!L2YdJ3mFUN@PwjNMXK{{v zwxiszj^!V>(*@*N+=3tte650Ofvf?mP|egp)4?6*oXFfd!^)A}Sq{ zICG*z5>IZ~%8(P1_;AEzOnBnJmE^U#GW#tv1O&j~y=@R|cpHLFewX!@jw3JZnqPlkqqgwY{6OUyLz z!-*NT%s632K4*g!i4w_qV1_WVoB`$v@2z8cIRnBpaJGAS1+z$P-y)TXd2@cyI|e(hoxPkUSdk(LnMT+#?_YK{Q8%JP1?k$YYj; zEX^Lx=Q@uE1=Xb0UE+Ej%&A3m&9acvtSux|3#oI&AxmpnL02R6>&d%UM-R_-KK;4* z@OGTO^YUxnUyxZegb6HFRjcBw1}6JvVO0>SMz0R3dC-fPJX=etm7^h?FecqcdiqMKErKMz(vVTW5GceM1#({mA%J5} z+bxF-uAKB2ZKuruZpjOPadGiYnz35bFx8wrbWqdrBI_O$A`BLb#p269`1o_tKg?*s zRM>(osfHn*q4m(2+D@BAm>xMZ45J@>;7EK1Awr5^4nibREh?s2j=rRD_2t6R$-(7= zl*Sbm7)wNIa%rP*XX~kjMJ@XSg@?x&lQvp@utZ5js>mSO!rDr@Jmvd?CN?)Y!c1{e z)M5R(vw!M(lz0U~8ReV`tR$BmLl^G+Z>O^kf?bN4j}SRUpiJb0tIdow$ljw&&J9H* zxojOQe3O^d7!^DpVViLIQKT4~WV_yeWR^%N(~uFSmLkm5zC(P2i&0jFsodTV{xBva zX;F;4A~Z@AUCR#^8RgXQlhz&O8RCxFv%*aXaO*Nr3F6&hMuog{i+9n0#zJACCQChjOsO)(W^NKq6 z45hxA)06d01mqepk)ROzUR*}gFn%&{l-*z@Q{xhQdcXOUmMnj2c(YQC)QKgw1Ucy{ zZ|A`qkAO|wW_}0;0>#bd58_$_Gq6Q4hCp$-!G@XDH}D`}K)Z@2V?qKOpS~MlKc}RW zWp_V~BsofYgT~XWQmfQD9m}!|Whg@#Dj6hA&ib${n{`u8Rt71%@@WhW#c?OsieD}N zREsil$#a!J>hQ_)(&WH>jlcQ7Eb+Gn!8m~+1F!+8bxi=Fms=hn1Z)JBH_ja@W^D|exdhGgi*exv0W zDnW`}^by5Dw~Ngff)KHb6gKWZKQk3k0kQpK<74NpuXYhcROsz)nkhn)W`^F;* z?FR2axTkHgwLkJ__PW-v3?OfGD=`=;Vb-ZqaHCZTwB>)u&pdQ=D0`N)$%n< z!~1V~3>wqYqHyyH&ZxA?kF~<4nv-&Uxjv!`*qST2*Y3`(^Mxy{AJ-CoLal!brFHT_ zvhXN^7J{<0qu*%L_~H&JYu+A_E~U3Metllm_z|VY{JB=c$8?kZD!ruft6O?P0d7EB zvc*YE0}%Jw3u^(iwlqWBtyixCfVTJCoMS<-U>9s{+k?xg)1t<9l_`yl#HC%0nVB1f zGd8(X(z?dXEEbQA9nztko!w_Eb!T97lZ;kvX*#P`G#P#H^RwlQbXRR==PI<)>?0x_ z*{VHEMrD+PM<5Px3X4#|w{Ql%o2wV%U>grU>T$Q&D5ib|+=6T|=DnRN4glDD)LxGy zPYttZ-C#FTiW)W&i;K~kq8ql$E0M@z=Y2@2QA*6#m8h&)hFH|FgT_L99Z?B{;pk6G03d`odI1watTK|sr9Fm4=d})V zoLOQnsVc26>qOlp2cS#lh;jRzo5L$p z_oMEKJD-_ju@E>On?1+owl;(m&v%4}t6uK>t|PqbmE7Tm_r+oQ#^^1?ZC=S5fR$NN zKhOaPAlH>EHT!TPrq?n^W+$-wQ+rUsJOeu(2zh{{a+La8@MV;n_&Kehf)%W&K*cNh zWU|UuO6>Acznc>1=9(#XPh$yA*572QO~^MWmxCw=PR$wc2(;F^j)5a&YQkt;XTUT>n<6BR-jFA2RRU;lcaNI z?zJK+6=3Hux;08kly65?6@+B0(ghK+9R{yqFiEglbs z{e&xX_jm}QEYKPfztfmItbDDkc8A^J^)9c(qqCgO4?BmsuXWRA$}!T?cOmGweu3|No;ChnioEgi zd#Nwg4>SzJsGnB<%3}sFoFfZBr~7xp`)dn}_5@cVE7 z;rr2+;ic7g0)J8GblnheoI7`&=@;j8P6%F*0Fe)hzIf`x!J-JF-&c~2_j8WDJ~VrV z8)I}B>!0Xu^bL^u){ef8XitoadD3I9wq&FXM_IHOg0#$E5b+N8Z!~aOI-Ji}A~tfT znUfn0%Eyks!ETgIo`w>LIz~`~KXGqQ;`m z0(_MfB8!AkM9i*CVE{r~A*}E?fL-}y)H~m(dp9CU-ksnEs;d+EL{rr{c3~5%F z`<7^>skFLwIhf7n86&m}D`eEJ9=jcgFDOHPtkYi6Klh#r9;W6y{SkbWkzC7A%W^g= z9IeoWv7t?&1vyW}Cezu9S7HJUIIuQkK6UjLe8W#4mUb_z|1UxK8M}X8nJ;>6rjfs-j@&hp zvDeW`6CL&Uhh0v%<^j)n$5;NyjT}M0O784SWF0ws-K?v%raBqmPrIFT-GiR@uCM)> z7deB4ivwBT&aRw#+GwV;f&Q|`DK|Xi1@HOBUrFRDGko0co(X3N&j~{W437bSF zzVw4l4mjryk9oyMe(+zx$X8C}goxgw>)_VBLk2X8#ygNPaRUiA&|7MK*A)+Kg z^e8P?6Q60Lr$K(Q#UU5mDtb~xZ`6LGxrW;7W3XRs zchqI~dfJ;l_iKU38n`^io@7JxP%T#rjdal0H-59jF<0E@8E^T*Z#j{zjL*W z{I~c&f2R^sM^rR)3`{KSTs(Z=;H`CqAug?`s;O&WlEq|H4B!U6J!A+JPC-pe&&bTm z!Oh$LN1@C@B4QF!GV)3)Y8qNP-Ftr0S>Mpu)I7_{$yTgkV&f9D(CpwM7egI6re|W~ z=5r+`DSMaxq<@}Qp{}W|i!d-UG0S2K5^B@`@<&}T06=^Y7y^Y;P}9=4@gt!MGb;x- zFTaq8SSOBj%OWKsucV@;p{1jzZ)ki^@pr`>Sx!l|;z%n>f>ascQ1GbOA7Rb6CsGbt zW==k(sx@jCFlf|7udJyrtd3l7o4pP@<)Z8E`_?nRdYAuyfRI|P4q{;w?f=9(B zB&TI=XG4BvBfzIrwMOj%2927q(t2C%>irE>1+{?L;9W^7jV{ITg6W+ve#N>7S>FwW zd?hONR;NWLgkT04PTt3yP?%`gXJTRJ;^7k%78RG2-gD>fT2Wb5T~k{ZVPIrpmc?Z% z`VZ3gto@jZjsXDTgTN3doPv7OZkC>rnU#Z^mtROkOhT$Nzh6<0^GYge8d^Gf`i91) z=Dqxbqa|oS9HgY$z`J_(&0qe*fBtLr|1swlddeb>hd)#9;P8ykX~Y$1SIOF;_Y1pl z#GFQ4gEps0o0Xkej-!YescBluV8@iwu2B6>XE#LwKniu|B?RoJ!w2O6t;qXu3qwsr28ZuRbTdR~5 z@AJc1Tnnvm?aSev!p|=f<3-Y4WVhB0|Bia&zNn6eH(m%_j!Ts!>*AioN}nI1e4@~! zFsLx4u(YsQS@^VYRcIHhaC)K4nA5C5PIEU%Wi{3WmIBI^_!ZP(LB$mlPG?DFNH_5l z&}if~9%tuKvB*#ok#8eo@aSdi+ZR)I>wEkA57Jzdg#r8Y5tVU}odp6ISc|Kb{==&* zX?``p9q$6gh6jSAFjRqiG_(RznNQxA-@x+Nd*)ey`d8WTpL}vM_V3&8x%YWDk$>y- zPR}pi1b;#(yR3hOrq$^UMw1y2UyWKfR7J+v|2tlY#pZB%e1XtcDt(J5T)}t$*oY)D zg-QeI3|}bsxg*F$RNbV_$<_jjex>Xm1em!3KWF>|&u9DsPa{9#4c<2a(trRd$h!!@ z${#wK_eIqOxgHmnz=rClnYnyW>c{Ro7y^YM$P}sy21gMoR62vnVskBv)UdjGLVW`W z4qyA!s#d>-;d#F@(P2hrR(4KqUVg1lvMy@l0CuP8m&E>2XbcvIClE>YB-BqPS146# zjaH{O7)@r2pMLr6kH6-p{@I?%lUwR_T<3LN_b>VWSATZUVMqPzxRXvh>%5EpcNxNR z)Hm0+)VJ2R)n8+}y7@t8Fj;JYP$ZT}Wpag*!{zahZ5hYy;pye=4a)W5)0c0*N|l<@ zXmxr6&9H#ujV80j>gwVL!wFI*_fM27lq$7kvF8#dgrSEUvN5s)3wxI{uVE? zRiVu)q#whA`04xG_P@TNv8lPG8-!7uq*-2+Ro%4udp4OZR-22fo4bdn!_vwcjltsZ z1b_+k*b9kFq0&IcLNBw}94?P95Q@YSsZ6d=s?-{-PH(8>FeGh&AaFmuA^YV6jltsZ z1R{w{q0;(Y=2yyOu{m5GUmz5TB{F&c{3%sxjaH{Onq15ltIh6ko>JFqOrrMiWC0jK zF`OXjmj^S)?}DsIs-_#JWjn6t2VoQ^X_gmdRX1(d592g1>vo*i{bc4`WnU-^jzFR@ z)mR*XNFr0HG&+OHVsp4WzM#%plK6m0Wpag5rPgS5dV|qqwzvQyOeo`hE>dY@B~lvA z-u|q%w0CrNb@%l4_4hOWvw^O%K2=P0lgA4CFHJYhFP7s4QIZu^(+$(IYgZ(BC}0$E zVUkvA4pdfk({@N6A#2vH`V(Z+<$9~-Z25fl9IRIX8MWEi?e%LpK}KViPeB+Lt7Xm# zWFvxN*(zl9XAR9%Z-Q(oh?2aMt z8CJ}BNmlgy=lDCOixZ?Dgi)NNSzc6i(+}e`FY9)km+S5Rcmf~VGDuIC3)oEK$PH*Gge%XXaC^H$TghSaS(+W&)8z5J~`PHE{j;`jdf<|QdW1)*2 zUeycpYoQt0JfD#0`j92a5#$L9BqI_!lc!->7200F6Wu9t?@x1r%LtfHB9+P8izt8h z@bt`w_2yAWvU-v=u6JMd$BPkV6%@L!N-&Yt>!7T&*duE&%EMWE|BV z#f+k_QCrg-`m$XYFTb8|S@;a?eKu0YY>_RR^&C61|2UcR&t8g8N`HLj&2%$Lsi#>w zFh9kk|GAXwfM#EuR}-D+LLS}dK`;8ykAY^;W>-r58GBd8wX+d>ACG`qUwt9;rUamG z-Tz(_Y~FYieen0<`qhWv)MKH=zP-;?Wm>F5AGy@Jr)I78$;D1NQd~K@dhrK=7Pm~? zj|nJy^Ucq*#~L$l`BCvH2Jkq2z(?NHp+DxAQ=0+T&BfclJrO%B*@9;*%(CKH+%~ps z8CubNR%>mKCat-Wywud@OUp>|rDgDmBWuapuqu(p1)VX)&rA~;%o_NmJF^eMoYH53 zX`e!V;t+k zF6nZv>>AUX(JW>+=ef>vehXgY;+C?E<*aaJt6AMXta0t@-OwgBx8-f__x5+P%Q>uf zvxqq{5~YL6fks5fC8nfje+w&T!WO;vQt z4gerN2n>P3DX3}b8JSr*xOw@7M8qVdWaO1p)F?r7qM}>;GtYh@%oR7>&19+>!X+zI zuh(ij9X7`b-`Qxpy$(6yoXc+d+kMXh-SvWAhLQu788U3-=&|D`PM&&87i)XoimR-) z&W6JGwA>0StERd>)L47H4K>kR%Wd|%{Z6`+lHNK{--#iDY@u9hhNAIgI-4(+tMz85 zrSZUu_;j|{=n=OyVLH;BlDO%HZPo)%**Fh zKU$xgACr&O=k~|t7uyg&jzrqJ={)bO3Szm%tUtlL|!nVwcM7{e43ZY$xqcr|pwzG+Z_o4SN<>(kk zXOiHFdAZO)p8#?y9=t+(homQtrI*1gxA(}-uH)6-mw0vd5U=jO!K=LQ@M`WUUbVfL z^=j=`Rma!itS%e*q$V^#OX{E{MYBF}ydYZX8?0+V{yseL&?ApM@w8{_=sAEInp)aA zx_So2CZ=ZQ7M4~)Z&@%PP#7G6M4_>`q&Gbo6e^9*V7{==pK?E>dqi3p%*N@@=53uyA)9$euU5+Ec<99Du3HB*Wa%g{&`b;q%f^8O zU?D^V6~iP5DOpC5Qxz&O2hSyZok!GEkYlLOVZw$BA0c9s{+N7q8D+;Rxk1a#c>%e_ z$nh+uw?uNAwnpyIc~|ZVSWoVyi?$;7iIoR@dH4_}+v}T4na@)CN+lh%4M__2!{rGr zyUJ{LS?nvTqeVJVHYba6x@c$0?rb@nE5`Y9x>zpB<#we!URhqRE!G>$=dIP$zV(OQ*Vh+(MtW zNTU|NuW?J3?yv2-8+3T@MED(z!OOtc-z zwWCI2M+?|{-RY$A%ue~oPJ3ZzytK34*tz=8&cpw9q2BchD0{Vxy#}7WJ{3;s zv*jJD2q)g;dhTrzDWcTs`de%MkF*&u`z5*z6lbo+uXLdojqU=&^X@JwT0@FYW{V}`9XPmcR3*x znbhcn=>hZ1{xCZVo}ZL!o1URDI^;)JTC|1^X_^#H^MVR>4tXl@$4dT)5;L1KJc}lc zqZ&T3tEQ0k{j>5+8qd4G_MjRZd`XH4lj*545xtRrWU)8wQPkSjtr&KT_m2=mwSY`w z6Udx{!8$-EuC}!q$2ajyEYb|KpwG+ha7Dl?-IID((4Bn8LSPo%izCR(WiyH!`Ww&A*FL?`=U} z@s_~$qMH;VmLjLC`6)>?zHSW?RG^bDv@*yveatZ17;`N)!P1A?>6RzWu+kbct#f5L z%hx<|REj4qdG3W|FTKMHNLBYRREKEfoJ3CXL-dq*${fFQ*{5eC+CKPsWN-SLavW}x zapY)&kEv=GQ{8^1VV5$Ex}0g;mBKXXx)x5;ZjEW)olJ}FV_J5KY1P9_>z-oT^p@qc z?VV0cyZ+G4dAra1d%7Gs3Dfn+Jw&G4frs~8gAJn(& zYx=DW8qhFH!C?HQlWbR_kJm$e z53g6C!4^80ofD6SDV99m7fT->-?8lR`SsQErmY070RafUnVm!-LNFG%04 zA=3lc^M1Nq8k9F!e)p5kUK>G4H2eQi4mf0tf1ESHf3CdcEJ%qfK4F7&wk1Xra`HM= zhU&NBX9Vb=j{!!QVum#~Ji?piXbYk-pnWG`^kLKEa!aq3Xbz$)U|tcQ4IK0WR0=8s zRf4KnGkiHAea%`n3_neRe&&~U+SziA8{FhJfAi1k&NN;7*UfU5`{l4$PB@F50T&<+ z5=?9(%)D3m)Yd@!8rtBTt)wNR>$~K&igRUcovAo=(f-kwZY-)&TT-RIluBcSN^|{{ z))!+-+rvvorKi1lc+jfOb#p#0*~9t#(^-A^n4QgI{;{~*kLAb4oLi>rxt0<8tGPXX zJ^sx7@$X5&4tRPzA1pd0{+OxXm2Y&d)+Z3Po4sQ%~czU;%Fr z|2*d-aK~E`S=z`-{Oplm?=@X7$GFnG+pfI)?r5+0gVn3=J;n6>shGVliuwENmc`d> zna|R0A=YL?^Lhn*6m|9qOzxowqz7Ofgbd0N7`KwRx0^z$GV=(U{KpLzwy{!S<7avP zUDR3ceI4V>PR5*elHjU2eAC_i9@N<8J+y=*OqEwxwXg1K3P@iu6Z|DxGtjUQEOIr5 zVyivjm(2-!Ibqc*i)J06##$zk~`k+T_N=WD?-OM}V-22SJmA06hkbm@s3( ziXBIDQUDijJ$gsq@_cFM_OkPhWqPJS0&EK=0gBqo?JRplDsm|`th_@qjhC_Ul(JbO z)fh^=;7nvvo9t@7CW-khU?GcG+?FQWVcAk`x!YOEDps>*SUYW5&$hNbA+wWR?AGvZ zIV1_I+Z!o?B+Uw}`b$7>D;+FCnJTH!7D(YpU%?RcIQQ)?`;glZqv1yn}5?};CZ35we;em1MT#jb@MaRQ>)JMS zINUT2$D;$rS6Ef8tn|R4iEiD?Ca1i5Sab!wtfZ<|`_)EUVSWFMHQcDvEoWuRUm?M2 zQdL&wW%VPjbaqx=S(UxjwR{)LxisUskT2Y5S~HVl3nbkQ&fTO>S9XTa)Wi^VzRXpo zrafa}Z13F6xa`Dm!R3T`TGE^aNl0Rn(p{C=Iix}%Q-a;zp7V2|rV(W%aXBT#M+^-$ zk>p$7``H>Bp|?SkD>B_Gc$Jk>^7Das)B+r4S{k#CN0Hz~1(* z##-xbpwT8;>_ri@9*RpBL*6lm@=%e4{)z+53g^kiOOUhTkYPK34!5~lw9D;@zA#R8VvI_DH@*MI4 zIvW}SjfTcS=R;GWAZRXB3iU#Zpch~{uw2;ntbJLRvp402qKZ*fsD|xh+jni>yWQY> zZdmcc&%3-Y27-DbWa(nc$lmp_mb&Y2=q(pdwJZiKwKLV3oZH15=hq2%rG+efG122k zSm|o^YPG9h|8{qH{qdj}G6ExRfD-N3O zt7_V~dDl^JBO|v;I8##R51qp}v(LnhyPAR#!oUX38krq*p70jW6@E@U;Lk#_E;^&Y zf5Y0p%*)(=YD=V^W=z7top12(3Lu@uf_{d z5cI}S!;CNz()Vruz?X}!2aHj??+af}2jBWBvaPQI_bxy4|LE0Evd8}O$iq3V-BdDW zmv>>smzAtb(lW0=zjCksl5g@X0n}fo!hflK@!@djE`Au_`r{DV;mG{ZZx!7)?`}S9 zk3M8;hVhtsZhGYJ9-Gm|H)OVcb8??5B>yr^|oC+ zQc(W7ITUSyM>}G&oSDG_IrMI-R%kVRM z22M*==a>#`_>vb#)Uvx+`WdrD8VhcpkVyw7U@cy)DlN5xg0i26h1Pv|@ejRYk!rd1wb&2(ay zd36*ksEN$b%eW^#(InqWy8Pn!Gqk?rQB#C>EKLJRaJ^3N9pfyFUOM?uAEUig5CEWG z0--bv91;f3Aoq^$(cDlu@(4QZO`QT!X$>JH3?2!*Q=SDXEL(s1ncgc zFX%z{ER{eagut*fFd{IU*9owJo;Vy!%u;scC4r@9>(daxU@1r;<|=TCRi+-orn{Y^ zRx=wyA{gG#oZdJt%*B3jQn9*n%Oo!vFqhi+39=^CdLI*)3YLey7icSjs2E)(8e`-P zi@Wgh!_!o*`bzUZ<0+X)g@b1QkgblK?&>a(D2w7DnkPJbnNABmN7%Sxq%sSy3%6OU ze`-mV<4M@6m>*S24J*Lj>kbvfrQ%$#KX0?unN~w)sy7*vJLoE|EgF|H&>o%LF_f!s zB4C`wJ2H73;jEm5vbgGTGd(nx5DJKoHolbVIjed2S&a&PQ>UBmKJJz=vOV>FA_}z5 zTkkYDb}H~7kbc&A<(WqhbI&!mbL$uu zc0Qc5^Z9)2X&F7QuJ?Vcxxr)9R7~7xFDC7`FJ-&i+x`xBWSlW38f$_{#+xiK z*?b{ay9LyHpwQf%o3#tG_upr`G-p@U61lUlzjNI=zF?j^*9ys8>-xd9%6CKE(5a=h zo&D`5g%1)3HI>oS;Fgi0v5C2bnXRMKRE4IPD#x>mY38W zzu)=u?#_FE-{0-%7KZy*2g^fsr2m;?I?c$IV_eg+G>9?7>M*@|OU|}^QP~}tLoqrWlQVHS8@E$&crz2H(sMFhSF&_9EBCwa z-z9mu!GT0#P-0#1#76(_*Fz}YQWD;Y1ol}%JD%Dml)qC_~s*Bnm0EFrTXqc9M^f}y%I-?iJ>lG& zwEL2AcT%26)uGfJPTi3-9PCC6+Y-}0iDlbEZf9)U6>7U<-HxPpG2AXByU$Y`=2v}d zgYSLk2kUK-(M01-FzKa~k-CW%{$Sp9+)2k=6l=CvapLy_LIEGx=kBPfSb@U*foMT5 z!}p#9_rz_cMWZG)50XI}U1sx3D6#m!s#NPWU*B$1_^?I>pY&uTJ6Xxh(>#v**}5oV ze=08VRx0BBC-WIDCR64F&$-NHs0dAO>`Gy!DpIjZRJt<7RkY%j%s|Ep2GH zF(Vc+Bp;GXe&mEWtTqKE#GHaq2zf|hLewdOoKY0fqZkrIam1Js6Jkk8sD!sjWkPhR zf>=-$nWP#rNOfd{8i)xs4|EVIq*~wrYKwz9ib37Z@(^FECxQ2M<^%os&>%iCgpUp5 z6QlUlR6aA4`c~0EG7a6Jky|vDLX+YRO^HO2(G10l<`aq^EoiC4(27t>XpK102GO7` z;!HcNG3^msIt;tsVfYRMCc^fZ4?AEx?1){k6HddgA$d$1320{aqgupfzp{mC;pfV_hPM?OVk|6rsQ4uK4@ z8wMi|e1p~CTf~v?Zr+II42BRQ6OdcXLUNdmykrjYoViFV^RSxC$Lg~HyT(GSE{kwb zSd2uo1es?cjA{$`09KCj;0e1lTPG_Q(W#<%NA>VZTyvKobtC#~~kaSVNBZ znWK_8*4sIb<9kl13@5GRl)ap`hBG#D)&U5kccP};{hZg z=0MVps3|e?#H7Fzq#))+O2i_SnJY>KqLA7w8mj^+NJ}h^h{peIN%@rx{m*1y;2UJX ztQg?}g~&v#1DRcIa#SKVf~=@TB(V}?LlL5gogo_i$WH7CInaw3VpqtC0pucff!zLP z4plPy)P8|E#1eZ!zMkm=LY#sEKOC4;^^6lxh#&qMob!xBp$J$*QFCIiD6os-=ID$U zSV2kRU?_zh#1W^V^k0rmy88FCP!{Fz60Z|D59LGPsIXjQ_EmDodyas?1*l9&Q3WnW zRYHk3;4)Mrbf^y3q6T3@O}G)Y2nMy`dekB8s7uhO2e+a=;l-Qq78=}T!d8F>(2$6s z5%K2r4knJKnR59wrzyl7n$^|jgg8TsqAdxz3#|g*qqXDWumt{#wjn;yF7P|rhdhS2 z1HYj|NC0#+zZxzf{?Iuv81IC{pi5v7-gTnuLIMNvJ|zlW!HsT|x9C0`zNMQtcFA{? zYD6fx=m{=-M5#wFpwXN13Vnb<-%YJQx(Ec(pYjC*Ac=vL4t#v1Fz5$m!?~Vi7(>7f z7)lw(FsQ=tn^8n(9YtVfj9zAAvYap&GsL8jG>i+pkMYEOn4qZ>2`r3Bfu&&bvJAK7 zJj2wl>P{j2ICvTTH3imim^ciMU>!#T58@a_9LGV06O=rh1U*hs zUf{H8b$~=E!dWA9hD0gGdC=hkr3AmD5f?8L)rC^vL%jMvM*pJp1sIP& z1RW8WnXE5~b#+WW=dOtfRuU4kL0^*KYeHs@=vQ*x9Q>8c@jXgv&rJpKB)JAzLT%p6 zPBGe}!4mN!LG-;2CdAK#z8}2j5t5oPPQmc7M6wfRye2HfAB44o-Vuoz+Utsm8!wjZ z_0Cpwf0vWM-Ux@C?S2xti*R1k29PD`7Wcfk={aM9O`}oXMde(ub4CO#EFZdvwmq zHTl(K9G{ymQ$H(x&TCo`n{YZy;C!NNhE-_caO3*~Gvr2KcSNoHY;^*&5)DhynZ@$e zuUs~ZWU^m+xCBloy1{dzM|?x{+rb|(znD|t5pv5aobttd%WwKSy%A%?L|<)Fu8$)l zeXGw)FoswJvx(*U)NsK>z9-fl(IpB5BDPiUZAb7ev9B8M+bC$RYv1L%nDMlJ_k*rfwbQNy_la9@kGPY1h{w>HAcurJJk-Q=O7 zw~**dC;f!#R2@U`jKp3)JC?2=^C*YtDM^q)5PWKpB*jOPs+r(v#~?`~jga&+ zMF=zYtjXwao%yKF)=vozldRw<$qtT?XTf-qQ)f^=r%v$B7YlzB9uNZ{9A+>wy zI?gGG#YQYx$%p}~82P}OF$&yQU=#)$7)8OxjgR>0WWWc&X1pJ4VJQH%;KLpA6F}Q;7f~&YUxQ+*b8;tzmCZiy@^)iZpckSPS`+~dR0pK1^1o!bk z@BsG*PjHX>TMtkfh=Rc=8=RUEQ7sY*LrR6nr~o-tpr8*ZsTvi|*6?d)U>;2Gk&i@z7v%ZZs0sm;Bgz zQpjLKS>&)ro@}DdboHj9!9tDsRw$q&hNBZYV=TI$J0_wBZMEv@;~(8N!>7NZ8H-eg zUh3Zqy~OW4@o?J&82kD_hrh=p_G`{?~k)x&azA zP0`}a(ti649lGY|(YLrCneS`KW8JNF=EsWiXlHWGuYJliuO+j#uDrg=f|ZRseb`uD zT`}ADE9V>g)9dz3-nGoauH@X|G{0jdhXK8h* zNhgD#MFuaKPCex<%b9FGo;jDp*K-$g`N{KNK7R!+6$((~N-^(5pb`oUUf{9PHv}nD zp05V?2Wr|ZK9qI|qj z+_g;f{ico5AHfq}DJqSK)pVoIzD!&M(ne#~qfNXUITS*N6HQALoh~Hlrs(xdvI*(N z5Ze#Y?f%D&(GYQ}jfrA12)v;Xvtf$X2-1vFEXI&-{ExAkuxZn`R{;VsP2Whw878OA z=CB~s{6_gEerj^sXsZQTmNvVkf@~|B!(Q<-lhel7E|YU5%4rkNZEY@}#kp0GD7T-J zN7_6Ni}USGo7Y=$fw5_0T@@Evnl_)G;vzHC=66zDY-8F29*Rp0Ok2=BnHLtNTgV@o zQghNR?2JsAE$J5VM5f%36p98`VMPJ4un#^IeT~4HAhyGSqH)<5+nM*G@fjD}mFuDj z`4!up*`kR#6|yIwNr-)#&7#SX7u$OkP06F!z6=&k&7Ii(tQAemmy}DBMANe)HkFs6 z8MzRf&O*`5_=_Eke9^3!OPMxcnjL4c!x1i;6I&_k21aw^Db^mzqG!iYtUr211L7uz zjabp*Sc##dRJ1TYVtJ7%Mi7(t4as|7E(k~Dy-u0JQDqK5WC1`p~rx{>Lnh^;! z6D*Bp#w?l*7NglQl@@|+(8Ab3OTfNpNt~yZ;3!%dw`nc7gw`fhv;ka58xk_w2(F-w z2_tO+SJI}0iMD{7XiLIHTfxn=HQ}c1;0D^BaL^9$G3`i9&@S)}?Mn2}ZtynkPIS>8 z@Hy>CEYV)@1?^3&(0=d}?N9EbL*P$3lmw&0;4eCygrMUPpyNp*oq!OXNRsFzgwx3+ zl}>>nbSjCZbC8G5B@J{53e%;ekuF04x}1EbD^Q58Bwy(^R71Cu33>?rrbl2RdK6vI zV=yT_j`z_MFecEGXp5eLvFT~FN6)}G^eo;+&%wC#JUXBkU@V{)(GI-?BLTgPX6O|d z1?W|@K(E25K(C`EdILrSdK0bCTQD-v+h~s70qdf7Vhz2k@p#@1d`0hp&Cz?CkL7)U zRnhzL1$_WkM<2v8`Vg#vK8)q`5m*y_6f5Xsup0U}meMESIQk_1rcc2!^lAJ_pMmG- zvqX_T2QSd)i86fw9-%K1N%|5zMqeg4`U*TwUnSD?HF$!)PGsmC@F;zgNYS_8CHgi| zMc;u}=(|J>eGgux?-OK z5J|r#)$|)=qu-Jm`W>R^_v9u00a@vfq>BE8()4H2O@Bcg{grgl-%ytRPI~Dds7U|( zoeVr(W8jchi40AYXff7`1v-rBL%w?P6Knokak4Fuqmlwun*F82AZELwT2 zHlABMP3WL;oiwSN#`G*~QLnzR`VAy*aN^kv@o2*n&tb%PKTS>a!}P*-%$QBnocYv! zpLmo-p54;I$5^&DBI`CfwmC7lt%W1A?MD`V`jwgA(>odZW5*k(zu-h1U^5WKsq^ri=)rObDRN z@TM#Ueadz@2Z@xc&P_b!Da289{hl+S7-&%(Zc@p@sVdc#iJ=;>qq?9#AHkaXH)}3` zuCGzbB;daWW1hY#4AZyucRZr+iw8?T)PEvIf8kt1Fh@fRL-cn&40~FFd|Hk?+K3w3 zghJYiYUcCKvy7Y}%fcD4815#ELmMkz+%4Alaucp$P3v|bSbI=nBRDA*nT_l&CPx96 zz?IS6rCc6^D`VkuIS$=r<#;q7J13yKq@0NE((*34D_h<3{2&NdkPm^IBAR*yG1L*n zrA{FcR5~OIgOY)|h-9YrBiX4vNDk^9l7~8t6zO$Fet=%PWC!%RB0HnkIoSohPRhNY z4r7bMEwB~9&9D{3EwL5B&9NQBt#EBQu8C`ha1Gp;iL2m_DO??Q+}Z=UD)!Fk2lg(s ze%QOhAK3e#bJz#KI_v{!#jq#BRvho*?l|7VeQ>;w{^IxmKF9GPdX3{7C7^Vl;(I8c zi=@RFslvlC0RPPfiUXM~c-v z=-E;7fQAFf8YHkPjH2}P2O1haB|W?fJUwLom=4r^5|Fh&OPWya+D=(jU_CIyhCK`> z?_i+I4_x#fv?qQK&tCNpWL9UiJ6d}kDyz!w590lmP(iU2S0BY!k5PH7ZTEPvE?r^7 zo>#Fa!hT0`0O$Xsux>-zpgMWV`Vd@T7uhK)VI?eLG_W-6$LNrukx;DN6Dn5%p`N5( zxa!;pbB6-c$x?ecO0P!Az{E3`$Va=FS55g;XDC*i_d^>K-)cxJWxE!G#SVtn!*{A2 zkyL7H4i)IU(nDrJ+S~n6ZvtiCqVfP%FeluhLkgC%x%a7fv9pq(Ve#GG?)30L&vDuP z#2jKYvGucAAU;&3Rq=A=aFL~6JnMGo@IYiC;qVD7JQ>wTHqXFv;95I;h`<~M{ZLXR z^D<+LN!{1NQ*Vv{Pd7sLdKk~*HuljG;^}I5x?ZC!s~^HReT0n0I-BzC?id!H?TBCo zGM_h|z@`E2n5Ljv3E6N4+8Q*=ZRU#wRKs2!%OgH2D||k5gMy5qUush^bu2VeK#i#h zHKlrLpk~yZ!*w*w5@y)!Cw6iT>}?EOLAQ=MUqkI~vjv-A35hb~`mclVij&u-=u z*}m*JgBneAy(fVg?M=ry>JyFQf=mm!OWMIDvXpktsn!IPK|TF(_x}qs(<&_KQAVh~ z|3M`4(aVl2fG#NZK(_PJ@XCJotx8QN#_hUIt@@i$DC#LR;_JCSH?4-xI-5BwJ4`ln z5WP2HP~C*Gg*Hw&ux$#C?vRx>MA^9e@BPA6u7YF5i&wdhZcqpmqG^NTEl^mq z4aZC1;+BQLDw`VB5kh%=VZVGe8-x5l48JNSzysAGwImx`K2%?4s;Hm!iXr&a-%r`A z>&lM3DGbJ&UK@3e%tenm_>?0xXYP2tY4^s}4BO_MA2x4ZbIR48jvmY@85Ybo1|`dz@D}V0Rt^hpAmnkt&!7~r5C%dK2jUE#5*E@xDC0n$ z!Kq-O41_8U)ETrI7TQ3l)|7}1>|t-P za)=|&4iOg!+znnHam3pp;sbH<mv%~bHea4;%@241*T`9*HA+k zg@?G>_+cN#?G0GW-Mz3hq~#rCo?l`@@?|@l(ITA~UYba&0n;UyhI!&h;baTj(oP4{ zp;gGyS{bo?XOm3+-`)adfCOX#3-O+CiNekxt9$lXsb#Xw#0U|HtPu@NTEVe;UQy!X znM5bze8#i2MMAu@cl6?Xdb{J}srsUf1rWtTAytL^JRF_W5hMaCz&bjRQ7Nt_DMR-p zekFc`ULc0M`=$qVX#UzRb#2|iWP`997?T2DO2l$Y8YC2{jAYwl7mcSDGf){1RE9uvDKBB6yTmV2i%@Vkpjv=)N zh$cem75+oAM369NmY-}H%%2$<4?zPW3U%rNu0~05*_QNm$wUsu=^hp`sdShunVRKX zSE_7~7L|%n5sJg*<62(PY_qL#tQgZ^sDk9??hzW(ga!mH-V7*T6{3`{Ml%d_S+*6F zO|bv}r2I{U+CrW39i5|5kWO7nkC>_!1Ul=ru;aJLQmqtWdt$vp z!#3*e{REkws7p1n4LvIzs=#DO`70uVz1VRE);7c7ac;=$MO?v;MJ4z}Ww8ELLhDq{ z{$N5Tj<<^{Z77?EPvw(B**T_n822I|AD1E(oz={$YV2qTKGiVeUog`!D5|;@J!MHx zS(*}}KuiFNd4;Cz!*a+MvaODg3NUpQvRM(1eAhe?S8Ha^c62PbQDhYrRe2b<6dT&*CfP7pyq1rS8gH6Sv_Dag7m%{{=$pB(d&(FL~iPtSu`TUWGYIRK@D zMXZNh-VycZ^{|GAUz<0&|P#gG|90(OSO)aw;G zm%(P6XW@7qcsl7kC0akChGrZ);+4Sxh@hVW2qNej5Sim-XKTez%h|WH61nmRWs*gR zyhxKM{l~*R>#jz-%WkCEW6+2EWM_ne&g|1A%TUG-0%i$B(0k;8uPILHpNZi=x=}gvryT8FSqt zUM(+?aBy(omr7&~1xBC)fl++NG0g&CCHVrLW<4`QUxOUq%8dndfu7TpFqm>DkRS>=;fl66EgY^qwGj+ihybz$(Qfj$ixt<@d8KpAmKA%F{2pAe z-WwVw#316uuw?^WIPkudXdG{WA99MP>C{hn^$JI~_kWBjd4G|w`O4r+3*~#JqxoI&a?T$ znKHjIg`SA zA!!!s#mmJ7`#1-Z*#>10MX-H_tqE2u$#}uOk66cvnEuB4c-`78F6}cM-4H4UVo$Wd z9ONvqzJ^|mA$2fIJUD=efUNFK2@94>A^;A8yIhF;Q~+W`$7{?0>momX26-mbskB|U zoAu_+3yR=1^-?Mvd{VW>#YjUXmWtVc*Iv($me*QD*e+sZEZ7dC8>MNrTb#kENCANY zz~9Uv+IipNlI5=>WiNHdgkuFL(c@I5)QbcR8oZd9y9Y&ijc($Fe;Xx=I0rHURHXt5?f-0yF*m%K(ZzU5(G^0Gg?i8g+j z$Gs+v@vnhk2|u=pNM|~Tt zMG=>|gmGjn(-JI|;@V^CZkeF24}sX_wxJBUOA97nrOa$$KW+xdJKlm_h%iGwvnxU_ z%0jWqp#d-xS@Q=dx!nG)$lqw+U$NH;=~c;)RxRs#O36JT>d;(M6V}5?KNl6K!jr)l z8T&>g90MWGNfMowClQlWBdfQZuQ;FI_KqvYIWsK)`DF^SSN@A!hE_G=E(vgekG8^t z7b7D?lf)WLV&!t={*WTcQP@s6bfNk_ecREG@8u;ZDlrMyAmS6eYB_QQ=%f_Se$}dw z{(=Lx1gJS+Hsa`cngaTtE)n(~M<3RCV3L`jDW!sn4I1+Gb4GyRQ9Gy0JW?gnu^Bds zZrl!5r`UpXy|JC&a`eY@0Tz4GV2i0 z7oIEdKtA40tecieA8Tf52pxOWR5dn{nag|OPsV=j7t?w!!mBHQ84y+7 zQghPcq+_ZF&88ovlsj-!FET-7tU+T05|rkb*@^Khh>-~%7p)-0q9OnX7$++Fye`K@ z8AV5dyH5%<eoKo1h7EWTu;3A2OhqnWLYpLH-1`L*tPU49(E&81r-pF>`;Y5K&j62$RnQu z{KKp8AHUO(A?RcDdV;!8h!KX7O62!*7Rd#cm zQAibz1Z@Kd-5i+*M9)4=9YX<2E#4%?QqCk|EJsa3wE!iiMJ5PLCc9R>1ti(NsyZxS zN3Ln=sU=(5qyHKP?Wj3&`!KJ*(H6l{fIN31t(r}HBWVCel*ydy$e>Rh{00563=@?- z)Q+KnFc~5lz;3y092$}$iX;z%(+K8nf$B<<#xk(RqukV_&@@Gpi$t?MmX|V`mbS%M z2)+I|Pa(@1E!ib*yJwqk3c0t${Bc7Mu*`;E2nP6~E-zL>Sk&rvo{ZpzIm!9hW@F}W z|7WLiKH^DHfW9D?=`iUPV}v5n&+Gz=#>T=6?pbF03!S3E!osdiFht#<{;ovEzD8)o z)TGjpH7TJeS{)TydsN?a@&~ ze}LyKN4X@xOxS;D;J@#af)a=cNAsmqgew{C;m8wJbOA?HJ+3jY^ZcU8i!MvfbUXP- z5AGhNzR$e)JgYx#`jvm0%h0NDvi?FeQpD0Rq67hp9q9l%S{7G2vB61R6ul50S*}~= z@*Xazo{-iyU%2wMpGyKG)o+6$`aZ=2s*#Miib8A)n#W6R0n;vA*4@&nZyQx)?p8;? zK`eHMn$!+0n*&-4*oI{z)ZlMn%5bK?+B{_me1n(@dX-Qy}Axd9x zHAZ>bA(JI&#a@~f42?jh$7>~pKWym~Tgf7Cx09x52wsp$$C=I1mubA#=gXM(jWYBs zs)ph%iGcQu@?c)$qex1|K>Dy3qmZ-uMSapHU@f5lNjKN>l;`T+o8aDSU*x&>Z~;p( zCM9x8aq6L8QhLnf7pbJyKv0N1Jlp!@OPg4L&@oJ?knb`u&Im#$ZLtS1rb=G76>_A+ zjIP?ng`P5Ln)YK0NK7<_NNP!=A(g|)YmD*r4nWS3cj2DP1eE%QIcjznGq5f(JGUzJ zU(xf?b@LopfB}ynGBlO)prkI6rb*?jN@o{$7$z!2N0Do0B9`$KAMJWh*_+Lp0FBU8 z&t0@w+cped3u>Rv5)N9b0GftBZN_mvw(Z?tnptSmh??{lAB@m8*vk~cxJJBb3mge; zH;DmI%0gl8lK+*wW3jeuO{oQhDw=QYMLcwFmve}Qi~<2d0iMh9Ba!E?7({$` z%S&D$7Phkx0(+)UU-dkTUVb=x>t|hmtTll!Sr3`Nf6u zKXAXrF3np5YlQ@RnZ_NJ5q{Yh{;SW9NxIDrQ+Yyk^seSo-4g~&dh~Ru+}nn0Wop~$ zQ@(m_*ot=z(pM6aASPxmK^#5}F$0+SYa29V92CJmZ7w~(Vf1)Gt6We|9~q3Xb$u3W zYSU5+u2D>{fq0{-?BTLWMfben`75LalwnKdE6II5yBQ}~JFjtG!+`~!EE?~k&{}M5 z5Kc_)520kg2L$fzTU(>mo-VV%QE?9K`X%g1qXjXA^&9)(1WnL(6?Fcu#a18Q!gt4K zIK7rMEgI8VO=y0+b5wPif>v*kuAMyvgj3UbH@he`PkVWy=sdhs{P#5uOAo*k7V%Jf>nxu%(VO5ilFxEhx+I(|ZFDH;10n?uvqj*y8qFhlUDHA|gxNC%v4gs{UJ*swpc@*qy@PqZw)^q z5&InHaf`Ra(8^<=@eLx{D_%A)y#0v)ZI2qQT!6K?wP#wj9kzZmZFA;Omf)U7t_`0r z@_!XMp5Mg;g9C~*sq4CepMZ&KwQvi&XzDWwejz)XK9fEGpZK;{ zeWjNipUtx^)kn}XvZ-^Q5u)Gn)#UywSFPscggyR6tKL_0%&UCzzh)_5T1j31UQZvs zU`~;-%F~$TTjZB-okri{wwBf_b>u=r2ao-y+PFTl zoN!Zs{?-HDp>}Gp&h|s~EY*Q;mDam#8%9S+P!b}q7t%x=^601u#5bU|aLo1>JQTq) zXgDvdQ|N=y2?_kd9(gV7JU8;)7B|e%oW5?TAt0@z&%(Ta2s~~bVj?LD7>hgkGB%Dt z!l{%eSe>AQ-ook0l}-o^`K+g`G1Q{wEwoC)ee@>EZdcYy*7UbY))}!AW0eBQ4c9AI zGPC7Q?&@LkMYoI{OF}zFpAg-1SMw+OB%hL%Vf#lk2ZXO9$7n%=9EUr~hRynn(qSV2PV+lG)9F&))8&zIN&t@|3b|jPO`88=n!4|Ip z_%4@mn-QIEV;`UGTbn(;-mLb5wJ$51xa|~V03?zN{HUCG3vmu%7_!O45>{8 zD3b?>9G5)O$`}RN_95w?MKZdll}D8NUONjS zS8fL~53o2SibxtQu1dRvo3~_85N!8oUDq$? zBFqI$5YnAOV3=f|?wJpMMf1~U_glxWcla6e{2U8KYy*1ot#?NLV}KX3wk4MXq+w>( zzd;6JyIyh2m*e~FnOpKBp+6AzM|QZD9Bnh#QiC<&%%rxt_A&$jb3V9pdAdMww_-VT zfvmsUIc*9btHHVW(61?({zAXw?ow+ZUD1z???YKz-?MdXPpil)Q86;2XMg}9iOC%= ztS+LEwSD9O?Avi7XD!b3#Y+7UcSv~7*L35zVWy|p1QMA{)BP3-d5TQ%&vXMsz5bMm zk*}-0W$ z3KJMbv#?}_{Of`YoNePWv)IgPtD8h#z#r5duyp=sVyre((>(G6S_C$z9 zp#emv^lRG>6DESJON&^w-~L$UV}HKE5dp@E2|b_|h)Hs64>d*s9f>#F`FQ7e*hht4 zFUGlH%t$`jQ$y|K!D!yeb@o!Pd>|AElny0d7H@6L1Y$4y z{ll#|wmSql^B-t1xed(3srT~}Ubc}ctyUY*L2ZbDQS@E?x));21ZWV@SM6B=GTNO^ z0-Bi6UJf(M-YX*I{&>#2l=O5@dH0t|t0M4f$r@m73fH*1BCQ6#2N6#8#n6BuqI_E; zjC0|UC#ukKTWoWnC|q`;T!tZAJPy0=s31skWYO^Gl77J|KvZcY@JJ98zC2efcNfZK zTowKw*Kg9ixII?Z#ob0@pd{*cjX;QO0;puB6 zT$HDmpO}r-bc{ATtcR2w_B=S!bN?KGE=_n#i0DQjqfR3g{8tNT2IHY2fPS8U`1JE# z7YK27N5#+Hl8dPMKe?3H^OF)v^iWd6J~#HcT*Q?Wpl%f#KSkOVK=`N$nphGO$=*S5 zZULob@jey(yLPiTiuqsiHI8S>PyOlm49vnOx2te57wh1sQS@Ge+lXhUejHAU@3G?= zXR=2_6NmR;LO+8~)n)5iej6Gei^d)N^P{dY^@UINk0$f;t;%SN3(N(Kvb zGjb+th+ZHM3V0P)B;{3}w84A>qn8$~FG_3-$mLd{*Fi5?QJ$AFc`pzek_fv*8uSC5 z@Y>)a+<-CflW}P-!x%#jr$uJ*9YD+%AtifVF_aPLI`(Oa3O#x67DxG-~HW_jm+SmtBi#y&o_U{4rTq${%!88)Seut^qZZndp^B4u73G z;N9vM=kR^ZgKi&vvg~{KrFEz4l+iVSn$JuWe#2JJ>d)S}uu8=5#iAAb_EPj%Y$mZ}WJ3zOKu`ZmZ! zl0CTr0jYh}h$mN#f^EMB{L3|GMo;GjrPFN4SqpIQ55)`fd^G%!#dA8EEA7`C3)*!= zVfnF>BdzE+?8O*T=ggOB4(|{P3Ky?u8_INynv@RG6N&H$q)@?PHfyI^Y{d|-M^sXl z+O&fR*6{@tfU><9%~sm-GcRv!uiEJ2kzH%p>OJ$TV?3mQzGXhR=r@5)AB-T9K(c^i zz-l+D&KjXe16sJ6-Sbl>ph|$@f1(%!vQ<5&d%^Wxrz76}mToiw?$}aR0?Y?vRGd>~ z!LH_njfPsLV8qG{N`Fjx_FC)Urhc-tZ$-wDl4T=On;&Chkex*zZUC5M*jk5QPe}{j zeN!UeT~ltP;3z2fK$}uK29OvL{==W$q^RJo$OkF)CM2c+OsLUI6#UWy#br**`>?{3 z{E`wSy?DjF0JRr`dXWw6q@NbHMPG@om1_*slEen;inYa9796(tmMy*A+H`@G`P01# z(De3D%GmL^ID;y|U{m!IWmc_f=e#Z^!)us@74|>+vPWL(6B*!Jz3d1O+n$D(Q3~C2 z2hYX>E1vLP8H0kgUvMyw`rA8sVB+B6qx8ukGP3%hv1`GUV|8LOpgU}YLx$ouu`X0S zI?_>7;B>q}x~GMAotvZMXJmW#jgyMqirr1-oO^(O^RX(<+UI>69>B z_bj7NraJbJRU>Kee1qr`#VfH((n}3KvF$ITTS&iwJj)cZ5vVAfK0Tj^)9cDMo0-w5AfoDriISY^A`QN$vhzB z#+LPHR)lOxnc|n>bREB1j7T^K`iou z40&i*Dz$6c=fU8DxY)xfplq?&j97h}K}PeGMAm{YQPn8i+P0M?;xL8tiFMg*) z-mx-WUl5=hIIg4~UBubOas}8><;e;G{!?5GuK=YD(R0NhyWohtj>*`VaP`hXB@(=u zp(AG2v;wZ4wsM#}HCp9oy#JQl&x}Cdh)B||nt1K;St~=@EE97)lJ0sPbTbg0dArxS zlxv;}*Q0mMZ-&uOuf)=r`pwN0b=Ii9bP1K>S%%*@d)iOHItPs6gMqa{@vma20$@K|yyhB+8TQH0LswD-??>R>o+oOVwVnm!|4R zJLEVh6k3b$slYoFL`4=Dn8b8ISWcf~BcqOby`h%m8}D=e9d!HFzJMmf!$|Hfc6s#3)DT0R~=3$`SRI)FJ`V(7@?UD0Vr`htoJAIcb1G?bN;RIEM3o z8x;gpMyRR^7m5$OrI2s8 zG1-+>!Ktk`*yBttuu|319%45qmbcZ3LeLwJA+x?M@gUFbrF5|sr0jPWQPb@4>V2Ry5G?pqB;0W)Uus+w^bosxxBYy9qgRD+ z45~Cai_%joYKX!+HRX%CI*f%hKUqY9#-5R^2dDnTerM=m#dZhmN`LaXH5xBfP8MC$ zU9os43Zx}TPAW0a3+a_CkATHMh>r@Kn2h;=@6wudvOdp=0w2YVG8)6i7d8W|qj#nwE=5j_k=b|RG{z*7 zgkoEEe=#J+ve3VjDZu_-qWV0F1ZZ;6F*>no{-D|eyA!wsJ}BMn8LK(8qef?kctQ4K zuSbh&`CRAlR1$zp%kbw41stO1w7aFGxht#pFQK5V#KjrY9%l5zN9y=UR$DLkPod?N z$O~7wUxRVHBCsizaaW=7Gam{|!i?OoV_)9B97!@StVd(*D-b&JABT_HT-K$<03q zFYH!Yc03g_B~pu#0US0e8i00Rv+=WkY3pwIA1$=nnd}cA`gFV~nk+!0qHFG5K?dfA zJfjVv6`eEbjcI_5lk7@-mXW|Z0P>c_FR>Q`RbEH%==67`-K?~wsnw}9%?mn9Sl7u9 zg^5ev^x6+;5~Ey-CBbj#DM~RcRe^@=mF*HM%CD}v6|>7JF2yDUVGkBU*xYQrCiEXL z;1JWpo(b`0Cf|Ux!mpfy`5kT$F)Jmbn!C*f#&59Xy?@P^a)xf%Nk*57w#nzVp>l;4S`uvA#h4tNh_TvI z>id9uoaoW4EBInTtAo+2xD)5iT8QIS=IwLbS%XI|~K(@qG>PKl#FI;9t4yr$oiqg$xN(B$zXb;p60!sGUewny1V5&^7vqymDig1A&yGJfeK(!A{A2yn~o*zkCjNTZr z-ymH!#Z{U)H|*t4!-$t{mu2aJW+wJFlCTqOlZ#3lXiAAmgh?gRc5Z@TTMUGYW*3J@ zk2;0TLBe%n^L!NZd)m=i5&R{$LK8b>X$O~!-`fm!ABrUP_b<+`@<=^i2K}U%dw-G6Y|E)4VL#c_MN;YCn!y(fs$eIQKBYvSfHDlvD32Ke zPrQGCT-8LISDTbWNpYunM#Bz4aG|VN>bCAPHtc^iFy{KH!`qa7+lg0Ox!dM7(<>m~ zYAoT6hcZsA^k?+ECH?n=c-5cqvj?8guC1mTPuPR7By_+gz8tLx-d`bs?;E#yZC{N08kezb~VIx+P+HRcX; zto|ZCT!yX4Wjs=@`n<-dqncmQgC%uZqM=Z-(@tdik<(=^-F&4C z=4y|%g$ZLnUOV;}x8M|=(-@!%O$x9maij4Ikrt=ySd6BS@4%Rf=v7?bI$%xhj6PJkgYR zud~evNuIkUXREsjt!W$%DJgFsG-pKkbjy_ zo{IH)PRTE2Y@EqtjkgC3W+M&QcD7|3m5fAtZcz9uD=`9+bC3;+K@f*-xP#u~QT{$d zQRV^BHFaPGcok~Wjyh7XDw;rRsV& zo$Ht9y|X}b{qsVPmP{cBD zdv5&|uAX_x!xR(-j--=aY>NA-2O z`W}8SN}`U~6rcweV@Zo;tCm=Z6!yMzaO*@%T$U!k$=F{!W-#_HY!2k=x^kQ)UCuI4 z-3Upkt zf9M(lq#Z9Ssaq4~<7t)m&4>5H{zh&%UXiAonNl%5sW@Iu;rZo!WyulR`6F+ksD;J; z!je!Xe#(_vOqZiqFN!LYFa?w}N@z99yUe0qm!B0t1s2UY)TwI)`SLGUy%?QhhzmvC z0xMD|G#%odVP^{FJkQbIE8CxKf13JpJj$bWDz-#xjiny>pKye|e>p*)-Xke=rA*-A zK??e;-o^2zz*JPHEKst|p4k`x=hU^;Ae(XzoO>k0fR0tJtvM0NdUJrLkdmJ47QVMt ztS$_@9kQC~x!5On)BvT_GBp>w^M#IB=t~L;F}>L*K)i z!|N1l0Tp14xk}H7*13%}>*wO0{OZrA`m(CyJ#RV628;J$kk;U4hKEk6t*=b7Ht9$d zJK9VuM9%^LY^YL|BwAAA*>A9805F)xqmO(~`+mt}=?9b}+1 zdeB1DgW{G*RR;#$3#E-iiwpt5LL?HD@KEH^oXfzMc1vYg8+p*Sr%Wf8SFZeBP}{!z z@V2_B9FqQ_GC`&-fLiLG@-SgXIAt5m<&13G2s1Vn-KEL2F-_HkZdjPsR!d#HI7QXb zhnXnTZ@MTUVWNuZB)VRg$ub$tU8!%B(B5>Yx%GnDD(X~JSlDrrex*LU=ac1Bxc80A zyL_@;vUAm`W8yWezJYGOvo8MsNi{!yHNAbU=u3atz5D+l;SKQ+g#Gt*PiwB_trAK( zl)oT5nX&%Qy@(OL!mj~l<1z%>|F^R$&`cvaqexW3tdXp4U|g~a2HZsq7_#Tsa*A!B zgWAT~Ijex%t@wbgEVa=+xov`mjn3^b?5;{hg~WW!Hkn)*w|#&fS+#iDP5q}lU3S78mdG_Asu zY0X-XYk3$~3G4$KR$Dc3tlI&JV#(6HXs4#DjD>fHkT?<c(O9k#mS=A9z%ra;8l_ve6`i~b3LZ8~Y$cNh(i2(Pf@EvyWu(H{tBT(SdC ztS{%N1Lwz?9HX#Ei1sH-ui_QcKky2oxs-Nw$H&l+x=(B6vMy~M%9dxCdN0bSB(*)8 zeVdwQsuSU*n%4ZCQkk~y*-#Y`_)qJ;xKs{3TVo88k>a(zo*%_|0<^ZJ!~H%_jM6Ke zL!B6sfHIrbawy7%Max{v1by3vHbre;pwK!C&sab~Z8b*^-Q~3`RqwWHyh#By!ftY^gj&IZZfakaMqid)jM~s3QyhR zhLs<1(4lPj8u9ros9r)Hf3>o1UGDMlFz$Ji^+wOU+~@dr;-YvO{ocUWZzC7K*qYv= zwO^W2K(|k_0vz@nTR!dwXNDZ(pO$yLNp2U6T{C{#9DaJ<#qbwL;F}(8U*VB;VX91{ z{4vf7aTjR%!@AMSbF1iS6Zm+ngqLsKk;!2+dnARF+%0*<_n>(ffs}Wy#9|f097n!n zy95Mnqt!`7FWsq|%pC|CXLcbFb#jIl|DIwGnVlRr_Qu(+Mu%nqvU%0L`alxqvLO(d z!nDDJYb_F`dXVZHgjN-}16z)|0{B{Iq(VDo;rg;v9khNfm=eSehZw} z^|Iw}5Mrxm=tNQm(4V)Z)tU=RFYn3<3+Ku#pizGZidQ!d0Gdmsmd;Y{<48-zZzwoQUBLg7q)#K%zz4G!$Rd@ti4@om=r<9YN zs9wFY=z)~7ZBAxA;p|H`4#>K!$93-gFDAJ@_rz=*K0@-AJEDG#wtKp~{qgqpVDoKA z)%6h8htSaKblVOlnqw@L@KfRFXdu8kr*AB`Ho_;R% z;_HaueTf5OxRv8oBlvNQx}r=Y=xS4z5 zdRt{_pC<36V`WtAHso1CY^IPSiwD&OH!z|YyJP1%6WR7y&UcFIIIuA=Cp1lt(@ofM zpra=cyRs`NKJ05%)JJ|MvRLdkqtkyTQlN4~D|YZsyjR)l5A*krQap^o>;-XYUiy%B zZVkVZE3ue2=;29tKeOf_cf@(7+mnp$58D#)FT~zx*Gsj5%t{BD&BH0t_jW{m>1J73JHd!m)J1WxgY~tlSr0 zo3KH~Q>BgtHC7ZPe_&S-7eBu-|2;&V{j>H+iLMKELw9+5xwv^CRa7?Um)rOM{2|kZ z9r3)0?w^Ps=5V;5&cm(%$j=HL3bQ`%WUzWUXAHWT18DmRA~e`DHu8#HU)ZcI*@PNn z*Yt@Vt{H(hD%;$heoy{d|`Yna-sT=-u|FO^8UoJyJ}M8+%VO**z(Y3UGe&dnpWGA))Irp$TC zT4nC|7xcBEM!kO*XyArj=#)0z!255v6eMQj4|$$;mKmlQ>M6fY%H}6;t?B4;=V;CN zdw54m-ZeNjaGjydf$?g`B9VbiQ1+@fQ_^dgFO?1W*-`MZjUD~M%Ux})B(!otk$SKc ziXo7`NX(n}Dk9?5JR@I=fK0-G<@IytU5$v}0-Y--M8^=Lqlq!m?>D@F$qi4D8y4Q5 zD!n(AA`G_5EVA6Vf|m5o^-|H-sTQ3}9<_cN0=ctDKgwm*iE4R-w`y6Opk;DEBI;V- zJcD2CMsJPzreg<#dL9Me)10Tb7=ox6Z#*T>*d;Fk-1)rVq7aO_l#>WRJr9kDZn!VV zVBLk!f5rSNC&ILl&lH;EwRW9xeMMS>#bYIQ0z!scwYk}l9$jsKpoksz+Tx)}x-P)& z{WV%_EM@v9pX4Pa(LM9JrWOJEF8Lr&_TJc;*ZVIFOY2(;bHKon3xL4P2DS9m7SM|P z7X|*1gOB9`#f!)l8vX=7-ZlWsyb6I_$%I{joF=$gaKda|8EbMpsmpHh^rh-{wP;mE zi)44FP2=JTm(|A}S9UF8C^sf|>*}O|3u&-)G#U6V+$aXI6bu|eC=;Y+E~J;Dx+LP# zNWm8wyxWcVf;nr&LK;mZB;ds&Dy>c^eqZvM#H2MTDXWtbSEq1xyX0qL+nNpCte+UP zhn(CEf%{V>07ll>QFGtt|8af?R(f1B@L||6ALlJ7Fl21_jk;kpX6pB-{EXb0zkQEU zUu-Jo$(!Vo7hbbMUAe-(@aFV;(0-OoX}|vXxH08-ES{e&vHYscWig}#j^is8)8#eG zHAFAMbs&6RY}bGR&N6~I7MVKvprJg$d-@^v7${Z84~<+c z%0Zb@xnjl*J19_Z5~&;=1AUH8P0lwCmIhXi;oBD)6q_6B)SDIdpNI zExC5KOs7#wkiy1R;gVP`BTi(1x%LFahstWalY95ZGl9BbPv9p>#-S8BN5t-W7@*^M z>DX(g&Wv}SIhj9kVtQAW?-!o6pmNNIFV|<$Q9J7ABdg4+>|OPmV_U5A;}+w0cuc_5 zOuJ*VSJ+AV#^x6u3D`PTUQ@oP-mhO4Su#G|?|Y*V3YlD*n(x# z;|MO%WV1(>ZJ8biraj9mmi^V?ZHI!|&J2P1plWPf`6FW7oUN&miY6l8!&cfYicnFMT*oGmwIyh===9X|@`Bha zJbGkio)7cvw>XL7pXzD&e~cL-AfJmrqxV&kF5inm83|{Gh<^DT?2IeI?nU*bPBz=u zMA50Lv5UpRSP>Az5wNKYAwlfcojQ|HxXU+lh6m6ssm1724J4MAWpAo3n>BOBx3e(r z+xM)E#r z6b7|%QuzH%8kbGslhNwKieZm@l5WH)WreE zy^p5&u(*bAqd>J`@A@HKMciktElhB56HyBpVRxq*q9OP;YbwHjs%cBHDhzI`Ilezl zKu>(Y08>aNazEKrU`p*zH9=k!)|A%fgQ4#Im;c7d2IAN-1hyjEVtV#z< zsk7SFy{`S0w-{L3HoJ;q#WR@{LuH+Vt1nq%liuj&W?%8T?^eu@su-T`PkCE`_l;^O zHq7szZz;B1%?qDf0jL=M4Ui{y(_H=Y7Fl0|)b~AzjIh;?%&ywBj`?Njo5i5KhcB7Z~iV zHUmp#e}zyvx_Srn9b&Zr%Tqlmg$ap_I>na8TC|?}2G&}fnjH}3D7G}D%ahTN*;bN< z2)tmW$l1DT$+yr1O-LTCTYwc;7cT`TiNb()o;IZ#Y3$0XW4pOlAagXSZ_^U4*pp6F z#kON=jH%Zk*<4pE-P~g`;i{)iookIPo7a5EcPOG$sG@AH(RE5!%?Vy5({>H+*)%m# zRoyUI-=X`Xzu~ILEul+07EAt@U=yY$s;eR$zf8L#bW5SWC~Y%uyt=k|vJtf|wlB9j zsi;`ORPdz?u_Q!7gdtqub-MD^^%T2pKrh`;-*0oa7?&urvAG2&y03ur?|$`wjdX4D@5`U&BpB!SPhXF_A{JOBX$Mg&Up44C zTr!Kw$4e!-VPT|47jj^}(xc>DkG~=k*d%GwsFg4E-_6z{Fr>Rp^a^tGv^lzeOJ|Oi z2}bGQceH2$(rFCT2Q>{5`KX$P?9Y7c~ZsSJBxZb>y$# zfrzkpU5R2K#ttYw*v;6ablz`nbBeb-Zi=lrQ#_o;dxGKsik4-WXnARVeC?NOk_QuF zS_bS01(|D?X@{Xxr$#HQ8pmrp@Bb}9OR{wJZ*(k&kS68{=_2{RYKm{BB#&yKXbRj_ z5LMDj6oyYExpjPj-0NPWs3oynOlz^b2;6g~DLu!6$y21cxU$q5gp?@n(%jrx<%_T@ zSNemPUfIafclPyG-|Fv|F(n*sm6Kf_U|aT{ofwbxYZKWzwlb~wpiocx5Dm2<=rG_p z6?kzLO{8B^6Fm9*aG*BxLwodA-<=|*Kt!IP*<#+cgI+u7+<>g((}=xzE3P?jQk__w ziSgS})DM$R-O_7X6iKXj8}JvKJwuv$N?_mow*D8jP%EAAlnDE8R2Dq)@^OKRYD0}y zZLF;>!v|pAM+KFa1q0=7`NWXkj!mCtp^J4fwp<@TRjj)`gPLDZB!{y>qJ1BCC~+R?9rHF37=M z5eea+3D>A4yiCDFj{K{Yh}1PY?T#5s9>L5|h)NqoMz9umnbY+s=06Xa*@}%p39++2 z*AXTcrVgc!U8*_4pKScK?boqStc?7*A%k)_zLPdgF#N6g11@SeqmE7a4(*uQv^ahYZYJ7@^Z=BeaV$wLfI1hY;HBx)t)R zqWvRnPo>2U#b`@j02I1YMc8ZnJFNc;~CbU6)1E2hA$hPlYM9MzIX}- zFFKs7d(W^akss8Ld@Q2kQAvC{F*g3{fb+(0=E=EHg4rwj@qa|b;^Xo-(i*TG+QSh) zTgtHqEHOED3Y!8eL8%3Qh0x7TX&!!v=^7(w4uwg^oIGino{I8G< z!mdVv2+L+`3`X_BXH#ZIPqxQkG`O?fh^s}90Y#?RK+5cOhu6loG#+S(U3+9*ZoldwdOEB-1Ro#b|U!=2Qh2gIp?u+)yM#WD^$AWXWw-kN8K6-wvCxJ?%+SI{F z0^7}9h1pr}%P+*#y{^7(%lG9~41PTgx83}{RDW|{4)EOVrX#h_B?B5P(ndHj?=f?Y zz=v0JsOnCo+yQzJzDn^v+{8$2?2gpn1kcAi{R=)!B9mYFOM^QyMzUNf&EI`uh{WVq zEDz|3-T7jHp2Tmcsk^Mg`u=qM118YyP9MRD3!DN!9HXP~d>NU9*r7u7yz4MW4HjGf zN5xC<(D#wE1S0M!E*K+ko+%dvE_>cSd*L=%8!=5=$?)Myb)~abbC4J?Qumza5oexD zOk8cfwLCb(|L1&=HmVY+!+1lKrvLe$pUPnU-!_B=rxv5&$P^^Ef`i&?O5q_ktD_X= zQeC;1f39ym`#e@{p0UaC-@nULhA8PP!0<#5!Td@&+mzkqZMXzQ`$ zk|ljwe3wg9F_SCGb^YjZ{7W>m%SX~BiJ!bNn=yg)Kn+#7B^K0j$jQ>u(tmhO)ykP( zWeuOvVKg!VHDU#EG(;N$_wLN%am192)j&9-aX)cZzY#J?;$nq1qXjG#r9osh^bS4h zSej}w&Y%6^m82g_n(^%WPaM<&=N(~dbO5%5Rewj6{acr z-Q_S(F0}~4S`LZBpFFJ#;}0lu@%bgodh~>Dub8hajg)Vk z-lIW8`hPm%3r-p}Cx;C5o@%K=P(f$cs(82>Cy%Wkyg<;MeWZtT`M26qELs3RO{@?y z_5frIyA3t>b7|>>nySV#?t$|s`t`VOo0x&%A`8Q~zA#?DG&k2?xICc4b=xJ3OfIx1 z!VdruS=0um6v92K12vav3Pu5?I2NR)_wLUYHufOj~{S% zgYEgpTO(>T<^SaNp;MKbq(%8!n_c&|15eO_WBaKpo!e$A>XE_GS!_p|fSLG!u09mz z$s$sI^isc;&>3L+J-6xdgt+gOJvcsWb`QaT-$)NKDFuI*{s%E(7os)Aa$kkd)rNdj z8-M?g+hr?=%~~Z_O?HCDtwRhx@K_U`OU0ielJ7y}EY)mZ@V8CB2bh4M|Fi#(K=993 znETm8sYP7b);k%{Q37RBSxwt$cX#GU35F<~qqs>xTEC2L4PV)PvIUV9OB%4f3wJ6x z%IeOCE@nQd>?v7&-M#XSFUmQ^UYRD)v|6)h3b87tsP0HKzW8~#WR>h~)J@*k4sA$X z6Lv>8=R z3u7A-J^U(_L$ouh+oqw3n8JvfG_#;yW7pJ)7+r>eo{27@n{4)Z>2_A;CJ>B|j0>@3 zR)`T|40}&h&%}UP^2k>w(%9=Y0&`88FhaznX}WDCD7P5_UrfjhwZ!J)VW3T!OorX- zBbx>6-|Rw>NWoKtFr)HH$3ziACQaXKF6*#x+45{&0r8LQHCRCue6Bxf)%YXOk~Lf@ zlgQ9Bn>1S2b5LIMPwm|OqU3t#x+hnmq(JBwZ|UBpzYg* z@2h4v6#JH!l6czqq&R$R_q)~&Ram*Qp2GI|;B2le4?h3cv9Tcfvu`zKser+y^Er$> zQ975B_KBOMqniP;h{suU{g~?0jUk?Omd`%PHo9ek(M###h^O(<4}XQpbN?NO!Kr?L zqwY}PklAUbOGqhVeyRMh`(U+ExvQr}si>%9!xU`7%*}vE2Wta|RwE-go!Bl2!-ZUf z_oHj?4WxK3nu{aiHQqd4=5}{-7PmYHN)|?#t6g9XI7_o~CDev=O$|{t4F%mqX%z|@ zDm{4SFO-x(qnLbXu3=Vj`f2cZ2pXG&LchZodaWE89i%}L`E;HlrW3P38up1xLw=1- zjs0JHzMB2|tNGEtN2Ny$Y!TU|u&%wnxl)SG(VZ3xnpp+`(aJ=-iqM`f;>m{=6l_%Z z?T552CI?Z6Th+eaR_YScODgCRZb|Md9v{F>htnBio`50y?VCwGy}ZpIIasVO_8r9c zy3uFZVm^-{ro;aQa`~@{b9vHo8m&a+vUuewbI}1#;_vi>lDPB+i5qeSJy(%p@w$Y} z(khySQM|yk1f89_DJe4ol&*p(KK|H`2$C|!kNt$6cWh}+UT;}Z7Tv< zv-1pv+4>6u3k7;X|8cVQ>v4*x9}>bttf~!JH{BB+6WV$$&@%W9j$Nm6Td5ZEFMaB@ z-75ldxh!GAp#fo^Pk#PRiOBTdZ&g|}P!1<%bCyn3#NSTzJnDSz@jYOTN#PGvjKCL= zVI8OoJn=_nu+Moi}Z_zSZWtHEbLz-$0kE)_V{8Y8t~@XwSm~E-4YK>DRI$g zlu*oD8CaSH0?bLZ)#V{NabA8amRVi}ep{TDF9LlQ-xahP<rasP(}=vU+Wa9P9W zgpR`*YJavL|CuE9V8%X1F(%LrbVj91Rr&$VS)k}A;ecd?El^|D;7inPNTQ0nFXNMj zEnUEk-|)Wv@34NZQgWju+TsLc2)QSD%#*;54C?GUG!vh5&FZuY`~V$q6imL9`s@c+rzj9c79+&exn?-l*5foPo z1*=xdAE%d(Tzi+qtB>&m5W>rp5)agFE@e)dt@t;?@5kpR&-+W9Nv(B-Bm97x^YfC! zo{34AG_+o4AdqKv@5L**2WEfm%e%{|N6)1ueyD@i>SqN0bP4O(kP`%bs@8J^$*)Lk!1&~;jmLX7Ms!vifC3xa1t&9zUz8iFV zFJo%3z^WK+ii*~{2HKXOWGX)$6RR!97Ka9j$WP;iY<>VG`JoJ}z`aX*4UFy@k;=*a zm00gR?50|2G^)+zqFSk_%t_mRn{yn-xn%k2k6Ue)ec7D+m~RMh%Q1f(d{!w)VIxc? zG{kJNsbODAy7l1#;7Zt61>L}~Yvf}m!W$AiYalyo8rX1)WV`!|A2C8xxf+lJ+6}3N@+DhZwj(e${*vVe7!)})O0RkB(X+@s281q~e6St+euc5EWN$sO=p=n^M zsH@kkONAj`79RfXGXuPL!{R`>-`t+q^oxYTF_m=nF516w%dKl$3i8Wq>k29gj5#U< zl*Vjsi5{e&AvALOY{_9BsSM+YDOy}l8#U#(wi(9t{1 zslJ+>kB7H<(-9p(tiyHL)vDTP!}ax9_m_VL>>cmdW4qlFo-zEr zAMmm^g!`p78_BtP*oQX~z{S{K#mtI=@%DkD(3^h1x5Z(t{Y|Zp^o5~c`Xir|oSc14 zr#F|(vy1UYL&O$>Nxz{q!WKcXvMg)*+V^Cz9O`+2DjjU?;VgbjVeV+CV5JO!%qXL2 z^hU+-27-z|=5Z9>_+w7{0jcNYP`WD79JRY{Xs^Yu1v)yf-f_y6mN(Q?0QVf|W2hte z-D0i@$1QUx8Uv0?I*cq+#aQa98m~O&CFBfprd7{5)zQeY%={ebyB!t5M} z8#pAs+bLmX@w1jzcxxDHlR7Xw5uQm$fdqK5W@LE~(dNuYnR3%f?4O`q^44ll^Zbsc zBn*ikElLs1H<5WIIT9wO;wgBMDoeWcO=MKe5y!rud>H0AlkqbqW9=LJz9Sic$TwTF zq^$L6_)kWNE##JUefW+0PP}-zI~tgp2BZriYJ#Ra(4aOjh854W_P(W&h8?0sHB%EgqFy1? z_^lpZdA5%u5fT)+5Kt0w4qH24p=O})B4;*}NSx}3CfnoB81qf4JyK06u){%wRaIm* zjZ45eY-d-<;t`X9+EpP|h|4(C7DE=;5-ekgC|PgA$O;Xwu9n61;A~}|D4w-Y_`!nunj=dUbFB@Eh@oo0J^Vei&l*vb`! zzBKRz#NLq_NG`3bFQ3>OHANTjlTzgY`nryITH%MK@&N;dM1)d}NWf@7LA}Dh|f`}c~Jv51-@WRQV*t$g7yA;_FxQ!9I z+5jHpn{|F!b32l!h4GoHAg$SyWN;dq{89ZKk&fzw>`g#WF#19BTA59zerQsc+sdmD zidkV7-w4*HjzTGynx{!ceiHO5rIy^vL=ZE0CZE*{3$XPNY4VT;l9#**56eulZTvv` z*f&ybNEYG6(BBvG5mrmI53O#|3bO>-OI3JP-+r| zZ1SOb95Z|wUmTtQM*?yY%b`i3QZvlZJ5*NdwAxx7o-ce-bSqR`y`5MZ$9g)3R>QolDv3oroKNHY_&T0LU#`RDzhAvvKXyi#mvuO zVO4bjT*D zdwwd`-Z1VNds?P3dMrwC9?CeiF998YM zl?J>X1(vOIt+2Q3LDczV3kJm!NyJOs{I+VU$Od~qc%8ArRkSRBn(=&045TFI)0i~& z(z{W!UblW-V@yCc<(TR-OsS_jAoITBaC{NMM|6Y-&n7MwLa`iuY82fS^Ahe9xS-f- z5H!^r?0Evn8QJP>P8eoDQlNfyjRw0UN3zRgh1 z0_XQs)`mqoDX%>5QQKpN>W{Y^@6SMWetn3UE22eL=sB7cw5byN@+4*+{ks3h}4U`oI zNbE1wKcRdSp(ZzX;Sg-$=FEltC%;pi^WzF zo99U!0XYd)$+EK+k=CA*3;YH-)23G+BBky0MtVnVr9(2)LTBsm`CYdBfY`KPw#8C> zwa~QW+;I^!0X^oF3hi^y(mEh;H&{K!B)9yj%7PoEbUZ(s437;Q+O|4!kqk})RaM|D zDRj=>gk^Gse84xDJV-XJ4&W$AdjCmRF8+T;^|ENI)(vZd$ifvzqn1Ptyu0u&@O2a}FJ`P? zoz38a*m}8m^wEV!6y*&>ao68ie@JLC*$-|>Es^V8R@1V;#&#-wv;sV@2vFoXw}Uf< zMjSU1fZY7=3-Y2Qv-AD`UI}r1f_^{6Z(+5z7%UXB_}I$Vi_VjnR5=P^qSFXBAI2%5 z1oPD9A8TtxxqqmV&sYCB?tjSnxP3#U<{_JD5=bkHEtOvr;S)(HXvI*pY(B<202&0$ zo+tBKIJ{Paf>JWa>AvFVLlkIjLNkXgwpdk&qDIGMw*yKn)@TK-tvnUh*?A(PbKodx z^Ga^{I zMb9frM}JU@iaSe5GikU(cvxraQPPtC(leSj{MNqf8u>z!PMfqDSdw1CpLV)%$(F5!v35O%6_YSeqcxaZ#uC1<{ zdAUajl1(gT5rV_XT-|*brwU?bE~4>i#c7X!c>gF51IyYcY3~fiTqDPo@=J+aWhKu5 zs%FcmbdDmwu&7?>cu-0RLl*7IW@uZ4`~il5(kuO8&6?W^NK)Xl{5-`$JJSL zayZs|jR>U*{2ZVO@SeSNt}=^Ig1&l@82xV$qtdG-*Ha@~gI|owjpIqc>XFiyaKM?z zk+*&euw`3YOWMV$fd!{NxS%v5$4kR$CGBY0uEVN zG%fArI?q?({J2H=+Whq-=AA@`ZS1xa?TvaTiFAQPzF6Mva9TQ@HNx`8-XFg@%&2i< z7ZS-k9y}O5={ULkCs#4K2$B6q6qq?oE{b%(taAjqr5ku=E=ysZ?1=a*;2?1&5?_~C z07XE$ztrtvH-a^;kM!i3xd;b>&4wLzxjM+Gqj~hL7!415zqGAvi|KhBF za9zw^?oR?_C+q;vC=iP7H)aZq1%*{Smw-?(V47!tlzgQU$mm_Le8MT~?-r_ft@jE? zanq=~gO(97$6Re9DcP@48y&*`@`k$%kCS7wOTyXwb^cVYu=qqcX-bVrn6ThjZ zf9lFsB*(|p{$%NiSE@(|TKA2jUzH9W*`IP%`8fZ7%wF@uz(cFox-2g|nsaXFDlljj z1hN+wZx!MO$_?x2Dulp51P5+*C=h~AiZ`JacSim&w~CaKRJ^LaY{hILiGhy%t`kk# zlt1Ji+LH5$>9o{c9f==bE@`_eb~zKao}S5W4)d_? zH;^};JsVeA`D+6x-Y<>SL(WWQ@-cB?hTgo#;hDivVX&>|)&|Jyapx;G7AkcX-KBzf z5;^VN&N4Y{3aK?u%6Oib_B*sL6^3v|h*YpPFhW}Ak|{++C7m}GRr`6Pt4Bu0)^&7_ ztr@d(`&-01u1nx4Ef;use4eMGl<(o8vUp1k^Kk0n0XWV=gBqpqp@mJsC-(W=sfO^B zp5nr=2m{}2ZD7>Rr*+yQ3c$a2zJVPlNw!BF9+*Y{D}(1nnXOSQ+}xJpiOT$;-K3ZW z#M_hpJ>On=d8utmUY^j&!zT%sPx|=$?Tj0XnZy9!+EG+i)c)co@NNI~)c74cg+_(e z9Pj`aB!ldpmDFLj%=R}wPx0h6Mssdh+N8(B*T4j6Z?7pxBdEc`!&fHp*UclBqYGkc zR&>6gPU3T`b4?nPzn-3C@RdbfnDW>?3372SB6&2@3D2NQL(CAN&|Xo>b@MU}kLmI* z3y|8ju*ep~e?PJ#Js%U7>;o5gQXr*M+yVE<*y_&M0~tl$6j<3!mcUsdN;EdMG{(*o zP4GQuO#h5+!bOPF`bzCH4dxN&UV{h(&)q`P=+|OUQU#uBtifruwOE>wL?Frd!YoUB zpc^T}VA~Phfp()bJME>@*1#CcbvEMPbVnjp4I=h{%USsi64e%ITcqR77xN4o92>%{ z%n*Tzmrw7!a;1}(3N5X4O6pp&GxmNU{tVNnNYw?_;=aHV@xsv$2d{_fpbXtu34;Y_47i3MfXk|pQ zrW7TS)*%bIQa;U!X@(@C-e2{l>$O}(tJz8X%30vDh9fq;uYao-0mi6`o5v92F5!1l zcLy=1Pxma*WqMv1sYws>Y6v zl?&%{DneHI5&YB;y2K>uqW!^=2b0gjx=8U&lxZxGDn=2!xh>!0j@8X ztj3G2I$PQ=ZyEDx>Z~^u7WaN(CY$*679_?0#iqjtLy63&p}Yi3@pvWFR#Mn!jlFH;3uG>X(N6c-2*_-S$c`PpR8JL?WDC^w<6 zG&=P$r>uA9v8=8S>6!zi1syjUZ}g^JT9Y^M=DYo_c7otvNlXyDS)wmlm zkyA-VHNv=qv>N*LvuvCGfce0tVv?VK*Kv2yd{23=4Wgd&4HF(nGhK*}jU}p&ZAlJo zy+`&IZxpzV3cJ6u7Wr%qtLkZ3tr48Y<`FXaQ1Z=7GrFScudBWu+MTy9bkuby|IpCJ z;C(na``-PYd#Aml%^yo*?T~cx?&n}?`k%jMY=R66q#EZ$$6!CHetN%07KY?in8n3y zX@WU24#jcQe-;~KF9g-#QgUFgk-BJij!y|0KtewW

TIWHPC<_9>em(Cvlhuf-BD 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 literal 0 HcmV?d00001 diff --git a/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 b/static.files/FiraSans-Regular-018c141bf0843ffd.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..e766e06ccb0d457fcdc8d4428efb796c7772a497 GIT binary patch literal 129188 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

)Thpg9J)x+@B(n?maf9&#`PQNHtKX<@|CQ`> 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 N#!G)s;2JO>~QPMdMZ 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

xz5_8aF@(pQs@zgto+ItjS_s2^}<|M=lFQ2 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,qWUc(1+qXDfx7@=bp~~)(TqS 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 Psah$GwaNdR#Q^{S={DW} literal 0 HcmV?d00001 diff --git a/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt new file mode 100644 index 00000000..4b3edc29 --- /dev/null +++ b/static.files/NanumBarunGothic-LICENSE-18c5adf4b52b4041.txt @@ -0,0 +1,103 @@ +// REUSE-IgnoreStart + +Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/), + +with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, +NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, +Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, +NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, +Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 b/static.files/SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..462c34efcd9d6b70b42359ca1a1d9476efe43eeb GIT binary patch literal 44896 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 V7)~)yDZnpu49h_gZvJhn{{a>V-DCg& literal 0 HcmV?d00001 diff --git a/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt new file mode 100644 index 00000000..0d2941e1 --- /dev/null +++ b/static.files/SourceCodePro-LICENSE-d180d465a756484a.txt @@ -0,0 +1,97 @@ +// REUSE-IgnoreStart + +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +// REUSE-IgnoreEnd diff --git a/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 b/static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..10b558e0b69a74b8329766fffbd5f64356c7230d GIT binary patch literal 52228 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 z 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 D0=ucW literal 0 HcmV?d00001 diff --git a/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 b/static.files/SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..181a07f63bef8f18e42a5a57463e0e60cf8e8035 GIT binary patch literal 81540 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 literal 0 HcmV?d00001 diff --git a/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 b/static.files/SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2ae08a7bedfed08cdfea76039c1bb1fa1d6cdf67 GIT binary patch literal 59716 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 tC40Gi`Mi4m<9BpxR%m?w=so8}_Gqj!BM1dG + +Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. +Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + + diff --git a/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 b/static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..0263fc304226d90e224e53053855ad138303b70b GIT binary patch literal 76260 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 G0RRB5qhxRZ literal 0 HcmV?d00001 diff --git a/static.files/favicon-2c020d218678b618.svg b/static.files/favicon-2c020d218678b618.svg new file mode 100644 index 00000000..8b34b511 --- /dev/null +++ b/static.files/favicon-2c020d218678b618.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/static.files/favicon-32x32-422f7d1d52889060.png b/static.files/favicon-32x32-422f7d1d52889060.png new file mode 100644 index 0000000000000000000000000000000000000000..69b8613ce1506e1c92b864f91cc46df06348c62b GIT binary patch literal 1125 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-G$+Qd;gjJKptm- zM`SV3z!DH1*13q>1OJmp-&A)3@J_A;A0V7u0bkfJ)-`Krrb zGey1(YybBo_r#8#3kPrfo#tA4xb3R$F4j$a9H~9huUPE$JQDstTM~O>^@Ps(;>UH<3Fx0=LBZUre@8723HjVToWun1;~KVtGY7SF1E7liM5< zHa%KaZ1y+v;MF5PX0dXM#bh1)zI}?P`JCclPp)GktoyD%Uv%1HzQp-VwViVJr}FN4 zBVAi3pdsabJ2zzio=sD>mtWX++u%m3k>>5t|1&=?+*B*EnLW)#$^O=9J{D1Fvz#4w zCmkrSML-}_v8Imc2?OP1;|%KWmLM+u&^dKy+fI{C57UY0UhRg-3U_ zKl;3k)jRBCi*uZh#-8L8Gwj!FXV37syULEeYD%&1+S-jgUC&wB|>?y4oO5hW>!C8<`)MX5lF!N|bKNY}tn*U&h` z(Adh*+{(a0+rYrez#!Wq{4a`z-29Zxv`X9>q*C7l^C^QQ$cEtjw370~qEv?R@^Zb* zyzJuS#DY}4{G#;P?`))iio&ZxB1(c1%M}WW^3yVNQWZ)n3sMy_3rdn17%JvG{=~yk z7^b0d%K!8k&!<5Q%*xz)$=t%q!rqfbn1vNw8cYtSFe`5kQ8<0$%84Uqj>sHgKi%N5 cz)O$emAGKZCnwXXKr0wLUHx3vIVCg!0EmFw6951J literal 0 HcmV?d00001 diff --git a/static.files/main-54bc299d2a5e4e43.js b/static.files/main-54bc299d2a5e4e43.js new file mode 100644 index 00000000..b4f20a41 --- /dev/null +++ b/static.files/main-54bc299d2a5e4e43.js @@ -0,0 +1,11 @@ +"use strict";window.RUSTDOC_TOOLTIP_HOVER_MS=300;window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS=450;function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden");const toggle=document.getElementById("toggle-all-docs");if(toggle){toggle.setAttribute("disabled","disabled")}}function showMain(){const main=document.getElementById(MAIN_ID);removeClass(main,"hidden");const mainHeading=main.querySelector(".main-heading");if(mainHeading&&searchState.rustdocToolbar){if(searchState.rustdocToolbar.parentElement){searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar)}mainHeading.appendChild(searchState.rustdocToolbar)}const toggle=document.getElementById("toggle-all-docs");if(toggle){toggle.removeAttribute("disabled")}}window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate");function setMobileTopbar(){const mobileTopbar=document.querySelector(".mobile-topbar");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileTopbar){const mobileTitle=document.createElement("h2");mobileTitle.className="location";if(hasClass(document.querySelector(".rustdoc"),"crate")){mobileTitle.innerHTML=`Crate ${window.currentCrate}`}else if(locationTitle){mobileTitle.innerHTML=locationTitle.innerHTML}mobileTopbar.appendChild(mobileTitle)}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";const HELP_BUTTON_ID="help-button";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getHelpButton(){return document.getElementById(HELP_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden");const mainHeading=elemToDisplay.querySelector(".main-heading");if(mainHeading&&searchState.rustdocToolbar){if(searchState.rustdocToolbar.parentElement){searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar)}mainHeading.appendChild(searchState.rustdocToolbar)}}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function preLoadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="preload";link.as="style";document.getElementsByTagName("head")[0].appendChild(link)}(function(){const isHelpPage=window.location.pathname.endsWith("/help.html");function loadScript(url,errorCallback){const script=document.createElement("script");script.src=url;if(errorCallback!==undefined){script.onerror=errorCallback}document.head.append(script)}if(getSettingsButton()){getSettingsButton().onclick=event=>{if(event.ctrlKey||event.altKey||event.metaKey){return}window.hideAllModals(false);addClass(getSettingsButton(),"rotate");event.preventDefault();loadScript(getVar("static-root-path")+getVar("settings-js"));setTimeout(()=>{const themes=getVar("themes").split(",");for(const theme of themes){if(theme!==""){preLoadCss(getVar("root-path")+theme+".css")}}},0)}}window.searchState={rustdocToolbar:document.querySelector("rustdoc-toolbar"),loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},removeQueryParameters:()=>{document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.hash)}},hideResults:()=>{switchDisplayedElement(null);searchState.removeQueryParameters()},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=").map(x=>x.replace(/\+/g," "));params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function sendSearchForm(){document.getElementsByClassName("search-form")[0].submit()}function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(getVar("static-root-path")+getVar("search-js"),sendSearchForm);loadScript(resourcePath("search-index",".js"),sendSearchForm)}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){searchState.setLoadingSearch();loadSearch()}},setLoadingSearch:()=>{const search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search)},descShards:new Map(),loadDesc:async function({descShard,descIndex}){if(descShard.promise===null){descShard.promise=new Promise((resolve,reject)=>{descShard.resolve=resolve;const ds=descShard;const fname=`${ds.crate}-desc-${ds.shard}-`;const url=resourcePath(`search.desc/${descShard.crate}/${fname}`,".js",);loadScript(url,reject)})}const list=await descShard.promise;return list[descIndex]},loadedDescShard:function(crate,shard,data){this.descShards.get(crate)[shard].resolve(data.split("\n"))},};const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}const pageId=window.location.hash.replace(/^#/,"");if(savedHash!==pageId){savedHash=pageId;if(pageId!==""){expandSection(pageId)}}if(savedHash.startsWith("impl-")){const splitAt=savedHash.indexOf("/");if(splitAt!==-1){const implId=savedHash.slice(0,splitAt);const assocId=savedHash.slice(splitAt+1);const implElems=document.querySelectorAll(`details > summary > section[id^="${implId}"]`,);onEachLazy(implElems,implElem=>{const numbered=/^(.+?)-([0-9]+)$/.exec(implElem.id);if(implElem.id!==implId&&(!numbered||numbered[1]!==implId)){return false}return onEachLazy(implElem.parentElement.parentElement.querySelectorAll(`[id^="${assocId}"]`),item=>{const numbered=/^(.+?)-([0-9]+)$/.exec(item.id);if(item.id===assocId||(numbered&&numbered[1]===assocId)){openParentDetails(item);item.scrollIntoView();setTimeout(()=>{window.location.replace("#"+item.id)},0);return true}},)})}}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function handleEscape(ev){searchState.clearInputTimeout();searchState.hideResults();ev.preventDefault();searchState.defocus();window.hideAllModals(true)}function handleShortcut(ev){const disableShortcuts=getSettingValue("disable-shortcuts")==="true";if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"&&document.activeElement.type!=="checkbox"&&document.activeElement.type!=="radio"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":case"/":ev.preventDefault();searchState.focus();break;case"+":ev.preventDefault();expandAllDocs();break;case"-":ev.preventDefault();collapseAllDocs();break;case"?":showHelp();break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementById("rustdoc-modnav");function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const modpath=hasClass(document.querySelector(".rustdoc"),"mod")?"../":"";const h3=document.createElement("h3");h3.innerHTML=`${longty}`;const ul=document.createElement("ul");ul.className="block "+shortty;for(const name of filtered){let path;if(shortty==="mod"){path=`${modpath}${name}/index.html`}else{path=`${modpath}${shortty}.${name}.html`}let current_page=document.location.href.toString();if(current_page.endsWith("/")){current_page+="index.html"}const link=document.createElement("a");link.href=path;link.textContent=name;const li=document.createElement("li");if(link.href===current_page){li.classList.add("current")}li.appendChild(link);ul.appendChild(li)}sidebar.appendChild(h3);sidebar.appendChild(ul)}if(sidebar){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Aliases");block("union","unions","Unions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("attr","attributes","Attribute Macros");block("derive","derives","Derive Macros");block("traitalias","trait-aliases","Trait Aliases")}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();const TEXT_IDX=0;const SYNTHETIC_IDX=1;const TYPES_IDX=2;if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector(".main-heading h1 > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const script=document.querySelector("script[data-ignore-extern-crates]");const ignoreExternCrates=new Set((script?script.getAttribute("data-ignore-extern-crates"):"").split(","),);for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.has(lib)){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct[SYNTHETIC_IDX]?synthetic_implementors:implementors;if(struct[SYNTHETIC_IDX]){for(const struct_type of struct[TYPES_IDX]){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct[TEXT_IDX];addClass(code,"code-header");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}window.register_type_impls=imp=>{if(!imp||!imp[window.currentCrate]){return}window.pending_type_impls=null;const idMap=new Map();let implementations=document.getElementById("implementations-list");let trait_implementations=document.getElementById("trait-implementations-list");let trait_implementations_header=document.getElementById("trait-implementations");const script=document.querySelector("script[data-self-path]");const selfPath=script?script.getAttribute("data-self-path"):null;const mainContent=document.querySelector("#main-content");const sidebarSection=document.querySelector(".sidebar section");let methods=document.querySelector(".sidebar .block.method");let associatedTypes=document.querySelector(".sidebar .block.associatedtype");let associatedConstants=document.querySelector(".sidebar .block.associatedconstant");let sidebarTraitList=document.querySelector(".sidebar .block.trait-implementation");for(const impList of imp[window.currentCrate]){const types=impList.slice(2);const text=impList[0];const isTrait=impList[1]!==0;const traitName=impList[1];if(types.indexOf(selfPath)===-1){continue}let outputList=isTrait?trait_implementations:implementations;if(outputList===null){const outputListName=isTrait?"Trait Implementations":"Implementations";const outputListId=isTrait?"trait-implementations-list":"implementations-list";const outputListHeaderId=isTrait?"trait-implementations":"implementations";const outputListHeader=document.createElement("h2");outputListHeader.id=outputListHeaderId;outputListHeader.innerText=outputListName;outputList=document.createElement("div");outputList.id=outputListId;if(isTrait){const link=document.createElement("a");link.href=`#${outputListHeaderId}`;link.innerText="Trait Implementations";const h=document.createElement("h3");h.appendChild(link);trait_implementations=outputList;trait_implementations_header=outputListHeader;sidebarSection.appendChild(h);sidebarTraitList=document.createElement("ul");sidebarTraitList.className="block trait-implementation";sidebarSection.appendChild(sidebarTraitList);mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}else{implementations=outputList;if(trait_implementations){mainContent.insertBefore(outputListHeader,trait_implementations_header);mainContent.insertBefore(outputList,trait_implementations_header)}else{const mainContent=document.querySelector("#main-content");mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}}}const template=document.createElement("template");template.innerHTML=text;onEachLazy(template.content.querySelectorAll("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});onEachLazy(template.content.querySelectorAll("[id]"),el=>{let i=0;if(idMap.has(el.id)){i=idMap.get(el.id)}else if(document.getElementById(el.id)){i=1;while(document.getElementById(`${el.id}-${2 * i}`)){i=2*i}while(document.getElementById(`${el.id}-${i}`)){i+=1}}if(i!==0){const oldHref=`#${el.id}`;const newHref=`#${el.id}-${i}`;el.id=`${el.id}-${i}`;onEachLazy(template.content.querySelectorAll("a[href]"),link=>{if(link.getAttribute("href")===oldHref){link.href=newHref}})}idMap.set(el.id,i+1)});const templateAssocItems=template.content.querySelectorAll("section.tymethod, "+"section.method, section.associatedtype, section.associatedconstant");if(isTrait){const li=document.createElement("li");const a=document.createElement("a");a.href=`#${template.content.querySelector(".impl").id}`;a.textContent=traitName;li.appendChild(a);sidebarTraitList.append(li)}else{onEachLazy(templateAssocItems,item=>{let block=hasClass(item,"associatedtype")?associatedTypes:(hasClass(item,"associatedconstant")?associatedConstants:(methods));if(!block){const blockTitle=hasClass(item,"associatedtype")?"Associated Types":(hasClass(item,"associatedconstant")?"Associated Constants":("Methods"));const blockClass=hasClass(item,"associatedtype")?"associatedtype":(hasClass(item,"associatedconstant")?"associatedconstant":("method"));const blockHeader=document.createElement("h3");const blockLink=document.createElement("a");blockLink.href="#implementations";blockLink.innerText=blockTitle;blockHeader.appendChild(blockLink);block=document.createElement("ul");block.className=`block ${blockClass}`;const insertionReference=methods||sidebarTraitList;if(insertionReference){const insertionReferenceH=insertionReference.previousElementSibling;sidebarSection.insertBefore(blockHeader,insertionReferenceH);sidebarSection.insertBefore(block,insertionReferenceH)}else{sidebarSection.appendChild(blockHeader);sidebarSection.appendChild(block)}if(hasClass(item,"associatedtype")){associatedTypes=block}else if(hasClass(item,"associatedconstant")){associatedConstants=block}else{methods=block}}const li=document.createElement("li");const a=document.createElement("a");a.innerText=item.id.split("-")[0].split(".")[1];a.href=`#${item.id}`;li.appendChild(a);block.appendChild(li)})}outputList.appendChild(template.content)}for(const list of[methods,associatedTypes,associatedConstants,sidebarTraitList]){if(!list){continue}const newChildren=Array.prototype.slice.call(list.children);newChildren.sort((a,b)=>{const aI=a.innerText;const bI=b.innerText;return aIbI?1:0});list.replaceChildren(...newChildren)}};if(window.pending_type_impls){window.register_type_impls(window.pending_type_impls)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementById("rustdoc-modnav");if(!sidebarElems){return}const h3=document.createElement("h3");h3.innerHTML="Crates";const ul=document.createElement("ul");ul.className="block crate";for(const crate of window.ALL_CRATES){const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";link.textContent=crate;const li=document.createElement("li");if(window.rootPath!=="./"&&crate===window.currentCrate){li.className="current"}li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(h3);sidebarElems.appendChild(ul)}function expandAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hasClass(e,"type-contents-toggle")&&!hasClass(e,"more-examples-toggle")){e.open=true}});innerToggle.children[0].innerText="Summary"}function collapseAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});innerToggle.children[0].innerText="Show all"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}if(hasClass(innerToggle,"will-expand")){expandAllDocs()}else{collapseAllDocs()}}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}})}());window.rustdoc_add_line_numbers_to_examples=()=>{if(document.querySelector(".rustdoc.src")){return}onEachLazy(document.querySelectorAll(":not(.scraped-example) > .example-wrap > pre:not(.example-line-numbers)",),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");if(line_numbers.length>0){return}const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{onEachLazy(document.querySelectorAll(".example-wrap > .example-line-numbers"),x=>{x.parentNode.removeChild(x)})};if(getSettingValue("line-numbers")==="true"){window.rustdoc_add_line_numbers_to_examples()}function showSidebar(){window.hideAllModals(false);const sidebar=document.getElementsByClassName("sidebar")[0];addClass(sidebar,"shown")}function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}window.addEventListener("resize",()=>{if(window.CURRENT_TOOLTIP_ELEMENT){const base=window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;const force_visible=base.TOOLTIP_FORCE_VISIBLE;hideTooltip(false);if(force_visible){showTooltip(base);base.TOOLTIP_FORCE_VISIBLE=true}}});const mainElem=document.getElementById(MAIN_ID);if(mainElem){mainElem.addEventListener("click",hideSidebar)}onEachLazy(document.querySelectorAll("a[href^='#']"),el=>{el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})});onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});function showTooltip(e){const notable_ty=e.getAttribute("data-notable-ty");if(!window.NOTABLE_TRAITS&¬able_ty){const data=document.getElementById("notable-traits-data");if(data){window.NOTABLE_TRAITS=JSON.parse(data.innerText)}else{throw new Error("showTooltip() called with notable without any notable traits!")}}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE===e){clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);return}window.hideAllModals(false);const wrapper=document.createElement("div");if(notable_ty){wrapper.innerHTML="
"+window.NOTABLE_TRAITS[notable_ty]+"
"}else{if(e.getAttribute("title")!==null){e.setAttribute("data-title",e.getAttribute("title"));e.removeAttribute("title")}if(e.getAttribute("data-title")!==null){const titleContent=document.createElement("div");titleContent.className="content";titleContent.appendChild(document.createTextNode(e.getAttribute("data-title")));wrapper.appendChild(titleContent)}}wrapper.className="tooltip popover";const focusCatcher=document.createElement("div");focusCatcher.setAttribute("tabindex","0");focusCatcher.onfocus=hideTooltip;wrapper.appendChild(focusCatcher);const pos=e.getBoundingClientRect();wrapper.style.top=(pos.top+window.scrollY+pos.height)+"px";wrapper.style.left=0;wrapper.style.right="auto";wrapper.style.visibility="hidden";document.body.appendChild(wrapper);const wrapperPos=wrapper.getBoundingClientRect();const finalPos=pos.left+window.scrollX-wrapperPos.width+24;if(finalPos>0){wrapper.style.left=finalPos+"px"}else{wrapper.style.setProperty("--popover-arrow-offset",(wrapperPos.right-pos.right+4)+"px",)}wrapper.style.visibility="";window.CURRENT_TOOLTIP_ELEMENT=wrapper;window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE=e;clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);wrapper.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}clearTooltipHoverTimeout(e)};wrapper.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&!e.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(wrapper,"fade-out")}}}function setTooltipHoverTimeout(element,show){clearTooltipHoverTimeout(element);if(!show&&!window.CURRENT_TOOLTIP_ELEMENT){return}if(show&&window.CURRENT_TOOLTIP_ELEMENT){return}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE!==element){return}element.TOOLTIP_HOVER_TIMEOUT=setTimeout(()=>{if(show){showTooltip(element)}else if(!element.TOOLTIP_FORCE_VISIBLE){hideTooltip(false)}},show?window.RUSTDOC_TOOLTIP_HOVER_MS:window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS)}function clearTooltipHoverTimeout(element){if(element.TOOLTIP_HOVER_TIMEOUT!==undefined){removeClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out");clearTimeout(element.TOOLTIP_HOVER_TIMEOUT);delete element.TOOLTIP_HOVER_TIMEOUT}}function tooltipBlurHandler(event){if(window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.contains(event.relatedTarget)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(event.relatedTarget)){setTimeout(()=>hideTooltip(false),0)}}function hideTooltip(focus){if(window.CURRENT_TOOLTIP_ELEMENT){if(window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE){if(focus){window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus()}window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE=false}document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);window.CURRENT_TOOLTIP_ELEMENT=null}}onEachLazy(document.getElementsByClassName("tooltip"),e=>{e.onclick=()=>{e.TOOLTIP_FORCE_VISIBLE=e.TOOLTIP_FORCE_VISIBLE?false:true;if(window.CURRENT_TOOLTIP_ELEMENT&&!e.TOOLTIP_FORCE_VISIBLE){hideTooltip(true)}else{showTooltip(e);window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex","0");window.CURRENT_TOOLTIP_ELEMENT.focus();window.CURRENT_TOOLTIP_ELEMENT.onblur=tooltipBlurHandler}return false};e.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointermove=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out")}}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){showSidebar()}else{hideSidebar()}})}function helpBlurHandler(event){if(!getHelpButton().contains(document.activeElement)&&!getHelpButton().contains(event.relatedTarget)&&!getSettingsButton().contains(document.activeElement)&&!getSettingsButton().contains(event.relatedTarget)){window.hidePopoverMenus()}}function buildHelpMenu(){const book_info=document.createElement("span");const channel=getVar("channel");book_info.className="top";book_info.innerHTML=`You can find more information in \ +the rustdoc book.`;const shortcuts=[["?","Show this help dialog"],["S / /","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
"+x[1]+"
").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";const infos=[`For a full list of all search features, take a look here.`,"Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for functions that accept or return \ + slices and \ + arrays by writing \ + square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);const container=document.createElement("div");if(!isHelpPage){container.className="popover"}container.id="help";container.style.display="none";const side_by_side=document.createElement("div");side_by_side.className="side-by-side";side_by_side.appendChild(div_shortcuts);side_by_side.appendChild(div_infos);container.appendChild(book_info);container.appendChild(side_by_side);container.appendChild(rustdoc_version);if(isHelpPage){const help_section=document.createElement("section");help_section.appendChild(container);document.getElementById("main-content").appendChild(help_section);container.style.display="block"}else{const help_button=getHelpButton();help_button.appendChild(container);container.onblur=helpBlurHandler;help_button.onblur=helpBlurHandler;help_button.children[0].onblur=helpBlurHandler}return container}window.hideAllModals=switchFocus=>{hideSidebar();window.hidePopoverMenus();hideTooltip(switchFocus)};window.hidePopoverMenus=()=>{onEachLazy(document.querySelectorAll("rustdoc-toolbar .popover"),elem=>{elem.style.display="none"});const button=getHelpButton();if(button){removeClass(button,"help-open")}};function getHelpMenu(buildNeeded){let menu=getHelpButton().querySelector(".popover");if(!menu&&buildNeeded){menu=buildHelpMenu()}return menu}function showHelp(){const button=getHelpButton();addClass(button,"help-open");button.querySelector("a").focus();const menu=getHelpMenu(true);if(menu.style.display==="none"){window.hideAllModals();menu.style.display=""}}const helpLink=document.querySelector(`#${HELP_BUTTON_ID} > a`);if(isHelpPage){buildHelpMenu()}else if(helpLink){helpLink.addEventListener("click",event=>{if(!helpLink.contains(helpLink)||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault();const menu=getHelpMenu(true);const shouldShowHelp=menu.style.display==="none";if(shouldShowHelp){showHelp()}else{window.hidePopoverMenus()}})}setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){const SIDEBAR_MIN=100;const SIDEBAR_MAX=500;const RUSTDOC_MOBILE_BREAKPOINT=700;const BODY_MIN=400;const SIDEBAR_VANISH_THRESHOLD=SIDEBAR_MIN/2;const sidebarButton=document.getElementById("sidebar-button");if(sidebarButton){sidebarButton.addEventListener("click",e=>{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false");if(document.querySelector(".rustdoc.src")){window.rustdocToggleSrcSidebar()}e.preventDefault()})}let currentPointerId=null;let desiredSidebarSize=null;let pendingSidebarResizingFrame=false;const resizer=document.querySelector(".sidebar-resizer");const sidebar=document.querySelector(".sidebar");if(!resizer||!sidebar){return}const isSrcPage=hasClass(document.body,"src");function hideSidebar(){if(isSrcPage){window.rustdocCloseSourceSidebar();updateLocalStorage("src-sidebar-width",null);document.documentElement.style.removeProperty("--src-sidebar-width");sidebar.style.removeProperty("--src-sidebar-width");resizer.style.removeProperty("--src-sidebar-width")}else{addClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","true");updateLocalStorage("desktop-sidebar-width",null);document.documentElement.style.removeProperty("--desktop-sidebar-width");sidebar.style.removeProperty("--desktop-sidebar-width");resizer.style.removeProperty("--desktop-sidebar-width")}}function showSidebar(){if(isSrcPage){window.rustdocShowSourceSidebar()}else{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false")}}function changeSidebarSize(size){if(isSrcPage){updateLocalStorage("src-sidebar-width",size);sidebar.style.setProperty("--src-sidebar-width",size+"px");resizer.style.setProperty("--src-sidebar-width",size+"px")}else{updateLocalStorage("desktop-sidebar-width",size);sidebar.style.setProperty("--desktop-sidebar-width",size+"px");resizer.style.setProperty("--desktop-sidebar-width",size+"px")}}function isSidebarHidden(){return isSrcPage?!hasClass(document.documentElement,"src-sidebar-expanded"):hasClass(document.documentElement,"hide-sidebar")}function resize(e){if(currentPointerId===null||currentPointerId!==e.pointerId){return}e.preventDefault();const pos=e.clientX-3;if(pos=SIDEBAR_MIN){if(isSidebarHidden()){showSidebar()}const constrainedPos=Math.min(pos,window.innerWidth-BODY_MIN,SIDEBAR_MAX);changeSidebarSize(constrainedPos);desiredSidebarSize=constrainedPos;if(pendingSidebarResizingFrame!==false){clearTimeout(pendingSidebarResizingFrame)}pendingSidebarResizingFrame=setTimeout(()=>{if(currentPointerId===null||pendingSidebarResizingFrame===false){return}pendingSidebarResizingFrame=false;document.documentElement.style.setProperty("--resizing-sidebar-width",desiredSidebarSize+"px",)},100)}}window.addEventListener("resize",()=>{if(window.innerWidth=(window.innerWidth-BODY_MIN)){changeSidebarSize(window.innerWidth-BODY_MIN)}else if(desiredSidebarSize!==null&&desiredSidebarSize>SIDEBAR_MIN){changeSidebarSize(desiredSidebarSize)}});function stopResize(e){if(currentPointerId===null){return}if(e){e.preventDefault()}desiredSidebarSize=sidebar.getBoundingClientRect().width;removeClass(resizer,"active");window.removeEventListener("pointermove",resize,false);window.removeEventListener("pointerup",stopResize,false);removeClass(document.documentElement,"sidebar-resizing");document.documentElement.style.removeProperty("--resizing-sidebar-width");if(resizer.releasePointerCapture){resizer.releasePointerCapture(currentPointerId);currentPointerId=null}}function initResize(e){if(currentPointerId!==null||e.altKey||e.ctrlKey||e.metaKey||e.button!==0){return}if(resizer.setPointerCapture){resizer.setPointerCapture(e.pointerId);if(!resizer.hasPointerCapture(e.pointerId)){resizer.releasePointerCapture(e.pointerId);return}currentPointerId=e.pointerId}window.hideAllModals(false);e.preventDefault();window.addEventListener("pointermove",resize,false);window.addEventListener("pointercancel",stopResize,false);window.addEventListener("pointerup",stopResize,false);addClass(resizer,"active");addClass(document.documentElement,"sidebar-resizing");const pos=e.clientX-sidebar.offsetLeft-3;document.documentElement.style.setProperty("--resizing-sidebar-width",pos+"px");desiredSidebarSize=null}resizer.addEventListener("pointerdown",initResize,false)}());(function(){function copyContentToClipboard(content){const el=document.createElement("textarea");el.value=content;el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el)}function copyButtonAnimation(button){button.classList.add("clicked");if(button.reset_button_timeout!==undefined){window.clearTimeout(button.reset_button_timeout)}button.reset_button_timeout=window.setTimeout(()=>{button.reset_button_timeout=undefined;button.classList.remove("clicked")},1000)}const but=document.getElementById("copy-path");if(!but){return}but.onclick=()=>{const path=[];onEachLazy(document.querySelectorAll(".rustdoc-breadcrumbs a"),a=>{path.push(a.textContent)});path.push(document.querySelector("title").textContent.split(" ")[0]);copyContentToClipboard(path.join("::"));copyButtonAnimation(but)};function copyCode(codeElem){if(!codeElem){return}copyContentToClipboard(codeElem.textContent)}function getExampleWrap(event){let elem=event.target;while(!hasClass(elem,"example-wrap")){if(elem===document.body||elem.tagName==="A"||elem.tagName==="BUTTON"||hasClass(elem,"docblock")){return null}elem=elem.parentElement}return elem}function addCopyButton(event){const elem=getExampleWrap(event);if(elem===null){return}elem.removeEventListener("mouseover",addCopyButton);const parent=document.createElement("div");parent.className="button-holder";const runButton=elem.querySelector(".test-arrow");if(runButton!==null){parent.appendChild(runButton)}elem.appendChild(parent);const copyButton=document.createElement("button");copyButton.className="copy-button";copyButton.title="Copy code to clipboard";copyButton.addEventListener("click",()=>{copyCode(elem.querySelector("pre > code"));copyButtonAnimation(copyButton)});parent.appendChild(copyButton);if(!elem.parentElement.classList.contains("scraped-example")){return}const scrapedWrapped=elem.parentElement;window.updateScrapedExample(scrapedWrapped,parent)}function showHideCodeExampleButtons(event){const elem=getExampleWrap(event);if(elem===null){return}let buttons=elem.querySelector(".button-holder");if(buttons===null){addCopyButton(event);buttons=elem.querySelector(".button-holder");if(buttons===null){return}}buttons.classList.toggle("keep-visible")}onEachLazy(document.querySelectorAll(".docblock .example-wrap"),elem=>{elem.addEventListener("mouseover",addCopyButton);elem.addEventListener("click",showHideCodeExampleButtons)})}()) \ No newline at end of file diff --git a/static.files/normalize-76eba96aa4d2e634.css b/static.files/normalize-76eba96aa4d2e634.css new file mode 100644 index 00000000..469959f1 --- /dev/null +++ b/static.files/normalize-76eba96aa4d2e634.css @@ -0,0 +1,2 @@ + /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} \ No newline at end of file diff --git a/static.files/noscript-0111fcff984fae8f.css b/static.files/noscript-0111fcff984fae8f.css new file mode 100644 index 00000000..a6c18eca --- /dev/null +++ b/static.files/noscript-0111fcff984fae8f.css @@ -0,0 +1 @@ + #main-content .attributes{margin-left:0 !important;}#copy-path,#sidebar-button,.sidebar-resizer{display:none !important;}nav.sub{display:none;}.src .sidebar{display:none;}.notable-traits{display:none;}:root,:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#595959;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}@media (prefers-color-scheme:dark){:root,:root:not([data-theme]){--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#a5a5a5;--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(65%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}} \ No newline at end of file diff --git a/static.files/rust-logo-151179464ae7ed46.svg b/static.files/rust-logo-151179464ae7ed46.svg new file mode 100644 index 00000000..62424d8f --- /dev/null +++ b/static.files/rust-logo-151179464ae7ed46.svg @@ -0,0 +1,61 @@ + + + diff --git a/static.files/rustdoc-b778ab399e080a4b.css b/static.files/rustdoc-b778ab399e080a4b.css new file mode 100644 index 00000000..8b90b805 --- /dev/null +++ b/static.files/rustdoc-b778ab399e080a4b.css @@ -0,0 +1,53 @@ + :root{--nav-sub-mobile-padding:8px;--search-typename-width:6.75rem;--desktop-sidebar-width:200px;--src-sidebar-width:300px;--desktop-sidebar-z-index:100;--sidebar-elems-left-padding:24px;--clipboard-image:url('data:image/svg+xml,\ +\ +\ +');--copy-path-height:34px;--copy-path-width:33px;--checkmark-image:url('data:image/svg+xml,\ +\ +');--button-left-margin:4px;--button-border-radius:2px;--toolbar-button-border-radius:6px;--code-block-border-radius:6px;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");font-display:swap;unicode-range:U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF;}*{box-sizing:border-box;}body{font:1rem/1.5 "Source Serif 4",NanumBarunGothic,serif;margin:0;position:relative;overflow-wrap:break-word;overflow-wrap:anywhere;font-feature-settings:"kern","liga";background-color:var(--main-background-color);color:var(--main-color);}h1{font-size:1.5rem;}h2{font-size:1.375rem;}h3{font-size:1.25rem;}h1,h2,h3,h4,h5,h6{font-weight:500;}h1,h2,h3,h4{margin:25px 0 15px 0;padding-bottom:6px;}.docblock h3,.docblock h4,h5,h6{margin:15px 0 5px 0;}.docblock>h2:first-child,.docblock>h3:first-child,.docblock>h4:first-child,.docblock>h5:first-child,.docblock>h6:first-child{margin-top:0;}.main-heading h1{margin:0;padding:0;grid-area:main-heading-h1;overflow-wrap:break-word;overflow-wrap:anywhere;}.main-heading{position:relative;display:grid;grid-template-areas:"main-heading-breadcrumbs main-heading-breadcrumbs" "main-heading-h1 main-heading-toolbar" "main-heading-sub-heading main-heading-toolbar";grid-template-columns:1fr max-content;grid-template-rows:25px min-content min-content;padding-bottom:6px;margin-bottom:11px;}.rustdoc-breadcrumbs{grid-area:main-heading-breadcrumbs;height:25px;line-height:1.25;display:flex;align-items:end;}.rustdoc-breadcrumbs a{padding:4px 0;margin:-4px 0;z-index:1;}.content h2,.top-doc .docblock>h3,.top-doc .docblock>h4{border-bottom:1px solid var(--headings-border-bottom-color);}h1,h2{line-height:1.25;padding-top:3px;padding-bottom:9px;}h3.code-header{font-size:1.125rem;}h4.code-header{font-size:1rem;}.code-header{font-weight:600;margin:0;padding:0;white-space:pre-wrap;}#crate-search,h1,h2,h3,h4,h5,h6,.sidebar,.mobile-topbar,.search-input,.search-results .result-name,.item-name>a,.out-of-band,.sub-heading,span.since,a.src,rustdoc-toolbar,summary.hideme,.scraped-example-list,.rustdoc-breadcrumbs,ul.all-items{font-family:"Fira Sans",Arial,NanumBarunGothic,sans-serif;}#toggle-all-docs,a.anchor,.section-header a,#src-sidebar a,.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,h1 a,.search-results a,.stab,.result-name i{color:var(--main-color);}span.enum,a.enum,span.struct,a.struct,span.union,a.union,span.primitive,a.primitive,span.type,a.type,span.foreigntype,a.foreigntype{color:var(--type-link-color);}span.trait,a.trait,span.traitalias,a.traitalias{color:var(--trait-link-color);}span.associatedtype,a.associatedtype,span.constant,a.constant,span.static,a.static{color:var(--assoc-item-link-color);}span.fn,a.fn,span.method,a.method,span.tymethod,a.tymethod{color:var(--function-link-color);}span.attr,a.attr,span.derive,a.derive,span.macro,a.macro{color:var(--macro-link-color);}span.mod,a.mod{color:var(--mod-link-color);}span.keyword,a.keyword{color:var(--keyword-link-color);}a{color:var(--link-color);text-decoration:none;}ol,ul{padding-left:24px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.625em;}p,.docblock>.warning{margin:0 0 .75em 0;}p:last-child,.docblock>.warning:last-child{margin:0;}button{padding:1px 6px;cursor:pointer;}button#toggle-all-docs{padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.rustdoc{display:flex;flex-direction:row;flex-wrap:nowrap;}main{position:relative;flex-grow:1;padding:10px 15px 40px 45px;min-width:0;}.src main{padding:15px;}.width-limiter{max-width:960px;margin-right:auto;}details:not(.toggle) summary{margin-bottom:.6em;}code,pre,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.125em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;line-height:1.5;}pre.item-decl{overflow-x:auto;}.item-decl .type-contents-toggle{contain:initial;}.src .content pre{padding:20px;}.rustdoc.src .example-wrap .src-line-numbers{padding:20px 0 20px 4px;}img{max-width:100%;}.logo-container{line-height:0;display:block;}.rust-logo{filter:var(--rust-logo-filter);}.sidebar{font-size:0.875rem;flex:0 0 var(--desktop-sidebar-width);width:var(--desktop-sidebar-width);overflow-y:scroll;overscroll-behavior:contain;position:sticky;height:100vh;top:0;left:0;z-index:var(--desktop-sidebar-z-index);}.rustdoc.src .sidebar{flex-basis:50px;width:50px;border-right:1px solid;overflow-x:hidden;overflow-y:hidden;}.hide-sidebar .sidebar,.hide-sidebar .sidebar-resizer{display:none;}.sidebar-resizer{touch-action:none;width:9px;cursor:col-resize;z-index:calc(var(--desktop-sidebar-z-index) + 1);position:fixed;height:100%;left:calc(var(--desktop-sidebar-width) + 1px);}.rustdoc.src .sidebar-resizer{left:49px;}.src-sidebar-expanded .src .sidebar-resizer{left:var(--src-sidebar-width);}.sidebar-resizing{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;}.sidebar-resizing*{cursor:col-resize !important;}.sidebar-resizing .sidebar{position:fixed;}.sidebar-resizing>body{padding-left:var(--resizing-sidebar-width);}.sidebar-resizer:hover,.sidebar-resizer:active,.sidebar-resizer:focus,.sidebar-resizer.active{width:10px;margin:0;left:var(--desktop-sidebar-width);border-left:solid 1px var(--sidebar-resizer-hover);}.src-sidebar-expanded .rustdoc.src .sidebar-resizer:hover,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:active,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:focus,.src-sidebar-expanded .rustdoc.src .sidebar-resizer.active{left:calc(var(--src-sidebar-width) - 1px);}@media (pointer:coarse){.sidebar-resizer{display:none !important;}}.sidebar-resizer.active{padding:0 140px;width:2px;margin-left:-140px;border-left:none;}.sidebar-resizer.active:before{border-left:solid 2px var(--sidebar-resizer-active);display:block;height:100%;content:"";}.sidebar,.mobile-topbar,.sidebar-menu-toggle,#src-sidebar{background-color:var(--sidebar-background-color);}.src .sidebar>*{visibility:hidden;}.src-sidebar-expanded .src .sidebar{overflow-y:auto;flex-basis:var(--src-sidebar-width);width:var(--src-sidebar-width);}.src-sidebar-expanded .src .sidebar>*{visibility:visible;}#all-types{margin-top:1em;}*{scrollbar-width:initial;scrollbar-color:var(--scrollbar-color);}.sidebar{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color);}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;background-color:var(--scrollbar-track-background-color);}.sidebar::-webkit-scrollbar-track{background-color:var(--scrollbar-track-background-color);}::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb-background-color);}.hidden{display:none !important;}.logo-container>img{height:48px;width:48px;}ul.block,.block li,.block ul{padding:0;margin:0;list-style:none;}.block ul a{padding-left:1rem;}.sidebar-elems a,.sidebar>h2 a{display:block;padding:0.25rem;margin-right:0.25rem;border-left:solid var(--sidebar-elems-left-padding) transparent;margin-left:calc(-0.25rem - var(--sidebar-elems-left-padding));background-clip:border-box;}.hide-toc #rustdoc-toc,.hide-toc .in-crate{display:none;}.hide-modnav #rustdoc-modnav{display:none;}.sidebar h2{text-wrap:balance;overflow-wrap:anywhere;padding:0;margin:0.7rem 0;}.sidebar h3{text-wrap:balance;overflow-wrap:anywhere;font-size:1.125rem;padding:0;margin:0;}.sidebar-elems,.sidebar>.version,.sidebar>h2{padding-left:var(--sidebar-elems-left-padding);}.sidebar a{color:var(--sidebar-link-color);}.sidebar .current,.sidebar .current a,.sidebar-crate a.logo-container:hover+h2 a,.sidebar a:hover:not(.logo-container){background-color:var(--sidebar-current-link-background-color);}.sidebar-elems .block{margin-bottom:2em;}.sidebar-elems .block li a{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.sidebar-crate{display:flex;align-items:center;justify-content:center;margin:14px 32px 1rem;row-gap:10px;column-gap:32px;flex-wrap:wrap;}.sidebar-crate h2{flex-grow:1;margin:0 -8px;align-self:start;}.sidebar-crate .logo-container{margin:0 calc(-16px - var(--sidebar-elems-left-padding));padding:0 var(--sidebar-elems-left-padding);text-align:center;}.sidebar-crate .logo-container img{margin-top:-16px;border-top:solid 16px transparent;box-sizing:content-box;position:relative;background-clip:border-box;z-index:1;}.sidebar-crate h2 a{display:block;border-left:solid var(--sidebar-elems-left-padding) transparent;background-clip:border-box;margin:0 calc(-24px + 0.25rem) 0 calc(-0.2rem - var(--sidebar-elems-left-padding));padding:calc((16px - 0.57rem ) / 2 ) 0.25rem;padding-left:0.2rem;}.sidebar-crate h2 .version{display:block;font-weight:normal;font-size:1rem;overflow-wrap:break-word;}.sidebar-crate+.version{margin-top:-1rem;margin-bottom:1rem;}.mobile-topbar{display:none;}.rustdoc .example-wrap{display:flex;position:relative;margin-bottom:10px;}.rustdoc .example-wrap>pre,.rustdoc .scraped-example .src-line-numbers,.rustdoc .scraped-example .src-line-numbers>pre{border-radius:6px;}.rustdoc .example-wrap>.example-line-numbers,.rustdoc .scraped-example .src-line-numbers,.rustdoc .scraped-example .src-line-numbers>pre{border-top-right-radius:0;border-bottom-right-radius:0;}.rustdoc .example-wrap>.example-line-numbers+pre,.rustdoc .scraped-example .rust{border-top-left-radius:0;border-bottom-left-radius:0;}.rustdoc .scraped-example{position:relative;}.rustdoc .example-wrap:last-child{margin-bottom:0px;}.rustdoc .example-wrap pre{margin:0;flex-grow:1;}.scraped-example:not(.expanded) .example-wrap{max-height:calc(1.5em * 5 + 10px);}.more-scraped-examples .scraped-example:not(.expanded) .example-wrap{max-height:calc(1.5em * 10 + 10px);}.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers,.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers>pre,.rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust{padding-bottom:0;overflow:auto hidden;}.rustdoc:not(.src) .scraped-example .src-line-numbers{padding-top:0;}.rustdoc:not(.src) .scraped-example.expanded .src-line-numbers{padding-bottom:0;}.rustdoc:not(.src) .example-wrap pre{overflow:auto;}.rustdoc .example-wrap pre.example-line-numbers,.rustdoc .example-wrap .src-line-numbers{min-width:fit-content;flex-grow:0;text-align:right;-webkit-user-select:none;user-select:none;padding:14px 8px;padding-right:2px;color:var(--src-line-numbers-span-color);}.rustdoc .scraped-example .example-wrap .src-line-numbers{padding:0;}.rustdoc .src-line-numbers pre{padding:14px 0;}.src-line-numbers a,.src-line-numbers span{color:var(--src-line-numbers-span-color);padding:0 8px;}.src-line-numbers :target{background-color:transparent;border-right:none;padding:0 8px;}.src-line-numbers .line-highlighted{background-color:var(--src-line-number-highlighted-background-color);}.search-loading{text-align:center;}.docblock-short{overflow-wrap:break-word;overflow-wrap:anywhere;}.docblock :not(pre)>code,.docblock-short code{white-space:pre-wrap;}.top-doc .docblock h2{font-size:1.375rem;}.top-doc .docblock h3{font-size:1.25rem;}.top-doc .docblock h4,.top-doc .docblock h5{font-size:1.125rem;}.top-doc .docblock h6{font-size:1rem;}.docblock h5{font-size:1rem;}.docblock h6{font-size:0.875rem;}.docblock{margin-left:24px;position:relative;}.docblock>:not(.more-examples-toggle):not(.example-wrap){max-width:100%;overflow-x:auto;}.sub-heading{font-size:1rem;flex-grow:0;grid-area:main-heading-sub-heading;line-height:1.25;padding-bottom:4px;}.main-heading rustdoc-toolbar,.main-heading .out-of-band{grid-area:main-heading-toolbar;}rustdoc-toolbar{display:flex;flex-direction:row;flex-wrap:nowrap;}.docblock code,.docblock-short code,pre,.rustdoc.src .example-wrap,.example-wrap .src-line-numbers{background-color:var(--code-block-background-color);border-radius:var(--code-block-border-radius);}#main-content{position:relative;}.docblock table{margin:.5em 0;border-collapse:collapse;}.docblock table td,.docblock table th{padding:.5em;border:1px solid var(--border-color);}.docblock table tbody tr:nth-child(2n){background:var(--table-alt-row-background-color);}.docblock .stab,.docblock-short .stab{display:inline-block;}div.where{white-space:pre-wrap;font-size:0.875rem;}.item-info{display:block;margin-left:24px;}.item-info code{font-size:0.875rem;}#main-content>.item-info{margin-left:0;}nav.sub{flex-grow:1;flex-flow:row nowrap;margin:4px 0 0 0;display:flex;align-items:center;}.search-form{position:relative;display:flex;height:34px;flex-grow:1;}.src nav.sub{margin:0 0 -10px 0;}.section-header{display:block;position:relative;}.section-header:hover>.anchor,.impl:hover>.anchor,.trait-impl:hover>.anchor,.variant:hover>.anchor{display:initial;}.anchor{display:none;position:absolute;left:-0.5em;background:none !important;}.anchor.field{left:-5px;}.section-header>.anchor{left:-15px;padding-right:8px;}h2.section-header>.anchor{padding-right:6px;}a.doc-anchor{color:var(--main-color);display:none;position:absolute;left:-17px;padding-right:10px;padding-left:3px;}*:hover>.doc-anchor{display:block;}.top-doc>.docblock>*:first-child>.doc-anchor{display:none !important;}.main-heading a:hover,.example-wrap .rust a:hover,.all-items a:hover,.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),.docblock-short a:not(.scrape-help):not(.tooltip):hover,.item-info a{text-decoration:underline;}.crate.block li.current a{font-weight:500;}table,.item-table{overflow-wrap:break-word;}.item-table{display:table;padding:0;margin:0;width:100%;}.item-table>li{display:table-row;}.item-table>li>div{display:table-cell;}.item-table>li>.item-name{padding-right:1.25rem;}.search-results-title{margin-top:0;white-space:nowrap;display:flex;align-items:baseline;}.search-results-title+.sub-heading{color:var(--main-color);display:flex;align-items:center;}#crate-search-div{position:relative;min-width:5em;}#crate-search{min-width:115px;padding:0 23px 0 4px;max-width:100%;text-overflow:ellipsis;border:1px solid var(--border-color);border-radius:4px;outline:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;background-color:var(--main-background-color);color:inherit;line-height:1.5;font-weight:500;}#crate-search:hover,#crate-search:focus{border-color:var(--crate-search-hover-border);}#crate-search-div::after{pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0;content:"";background-repeat:no-repeat;background-size:20px;background-position:calc(100% - 2px) 56%;background-image:url('data:image/svg+xml, \ + ');filter:var(--crate-search-div-filter);}#crate-search-div:hover::after,#crate-search-div:focus-within::after{filter:var(--crate-search-div-hover-filter);}#crate-search>option{font-size:1rem;}.search-input{-webkit-appearance:none;outline:none;border:1px solid var(--border-color);border-radius:2px;padding:8px;font-size:1rem;flex-grow:1;background-color:var(--button-background-color);color:var(--search-color);}.search-input:focus{border-color:var(--search-input-focused-border-color);}.search-results{display:none;}.search-results.active{display:block;}.search-results>a{display:flex;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);gap:1em;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:2;}.search-results a:hover,.search-results a:focus{background-color:var(--search-result-link-focus-background-color);}.search-results .result-name{display:flex;align-items:center;justify-content:start;flex:3;}.search-results .result-name .alias{color:var(--search-results-alias-color);}.search-results .result-name .grey{color:var(--search-results-grey-color);}.search-results .result-name .typename{color:var(--search-results-grey-color);font-size:0.875rem;width:var(--search-typename-width);}.search-results .result-name .path{word-break:break-all;max-width:calc(100% - var(--search-typename-width));display:inline-block;}.search-results .result-name .path>*{display:inline;}.popover{position:absolute;top:100%;right:0;z-index:calc(var(--desktop-sidebar-z-index) + 1);margin-top:7px;border-radius:3px;border:1px solid var(--border-color);background-color:var(--main-background-color);color:var(--main-color);--popover-arrow-offset:11px;}.popover::before{content:'';position:absolute;right:var(--popover-arrow-offset);border:solid var(--border-color);border-width:1px 1px 0 0;background-color:var(--main-background-color);padding:4px;transform:rotate(-45deg);top:-5px;}.setting-line{margin:1.2em 0.6em;}.setting-radio input,.setting-check input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:2px solid var(--settings-input-border-color);outline:none;-webkit-appearance:none;cursor:pointer;}.setting-radio input{border-radius:50%;}.setting-radio span,.setting-check span{padding-bottom:1px;}.setting-radio{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:inline-flex;align-items:center;cursor:pointer;}.setting-radio+.setting-radio{margin-left:0.5em;}.setting-check{margin-right:20px;display:flex;align-items:center;cursor:pointer;}.setting-radio input:checked{box-shadow:inset 0 0 0 3px var(--main-background-color);background-color:var(--settings-input-color);}.setting-check input:checked{background-color:var(--settings-input-color);border-width:1px;content:url('data:image/svg+xml,\ + \ + ');}.setting-radio input:focus,.setting-check input:focus{box-shadow:0 0 1px 1px var(--settings-input-color);}.setting-radio input:checked:focus{box-shadow:inset 0 0 0 3px var(--main-background-color),0 0 2px 2px var(--settings-input-color);}.setting-radio input:hover,.setting-check input:hover{border-color:var(--settings-input-color) !important;}#settings.popover{--popover-arrow-offset:202px;top:calc(100% - 16px);}#help.popover{max-width:600px;--popover-arrow-offset:118px;top:calc(100% - 16px);}#help dt{float:left;clear:left;margin-right:0.5rem;}#help dd{margin-bottom:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;padding:0 0.5rem;text-wrap-style:balance;}#help span.top{margin:10px 0;border-bottom:1px solid var(--border-color);padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid var(--border-color);}.side-by-side{display:flex;margin-bottom:20px;}.side-by-side>div{width:50%;padding:0 20px 0 17px;}.item-info .stab{display:block;padding:3px;margin-bottom:5px;}.item-name .stab{margin-left:0.3125em;}.stab{padding:0 2px;font-size:0.875rem;font-weight:normal;color:var(--main-color);background-color:var(--stab-background-color);width:fit-content;white-space:pre-wrap;border-radius:3px;display:inline;vertical-align:baseline;}.stab.portability>code{background:none;color:var(--stab-code-color);}.stab .emoji,.item-info .stab::before{font-size:1.25rem;}.stab .emoji{margin-right:0.3rem;}.item-info .stab::before{content:"\0";width:0;display:inline-block;color:transparent;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;float:right;}.rightside:not(a),.out-of-band,.sub-heading,rustdoc-toolbar{color:var(--right-side-color);}pre.rust{tab-size:4;-moz-tab-size:4;}pre.rust .kw{color:var(--code-highlight-kw-color);}pre.rust .kw-2{color:var(--code-highlight-kw-2-color);}pre.rust .lifetime{color:var(--code-highlight-lifetime-color);}pre.rust .prelude-ty{color:var(--code-highlight-prelude-color);}pre.rust .prelude-val{color:var(--code-highlight-prelude-val-color);}pre.rust .string{color:var(--code-highlight-string-color);}pre.rust .number{color:var(--code-highlight-number-color);}pre.rust .bool-val{color:var(--code-highlight-literal-color);}pre.rust .self{color:var(--code-highlight-self-color);}pre.rust .attr{color:var(--code-highlight-attribute-color);}pre.rust .macro,pre.rust .macro-nonterminal{color:var(--code-highlight-macro-color);}pre.rust .question-mark{font-weight:bold;color:var(--code-highlight-question-mark-color);}pre.rust .comment{color:var(--code-highlight-comment-color);}pre.rust .doccomment{color:var(--code-highlight-doc-comment-color);}.rustdoc.src .example-wrap pre.rust a{background:var(--codeblock-link-background);}.example-wrap.compile_fail,.example-wrap.should_panic{border-left:2px solid var(--codeblock-error-color);}.ignore.example-wrap{border-left:2px solid var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover,.example-wrap.should_panic:hover{border-left:2px solid var(--codeblock-error-hover-color);}.example-wrap.ignore:hover{border-left:2px solid var(--codeblock-ignore-hover-color);}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip{color:var(--codeblock-error-color);}.example-wrap.ignore .tooltip{color:var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover .tooltip,.example-wrap.should_panic:hover .tooltip{color:var(--codeblock-error-hover-color);}.example-wrap.ignore:hover .tooltip{color:var(--codeblock-ignore-hover-color);}.example-wrap .tooltip{position:absolute;display:block;left:-25px;top:5px;margin:0;line-height:1;}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip,.example-wrap.ignore .tooltip{font-weight:bold;font-size:1.25rem;}.content .docblock .warning{border-left:2px solid var(--warning-border-color);padding:14px;position:relative;overflow-x:visible !important;}.content .docblock .warning::before{color:var(--warning-border-color);content:"ⓘ";position:absolute;left:-25px;top:5px;font-weight:bold;font-size:1.25rem;}.top-doc>.docblock>.warning:first-child::before{top:20px;}.example-wrap>a.test-arrow,.example-wrap .button-holder{visibility:hidden;position:absolute;top:4px;right:4px;z-index:1;}a.test-arrow{height:var(--copy-path-height);padding:6px 4px 0 11px;}a.test-arrow::before{content:url('data:image/svg+xml,');}.example-wrap .button-holder{display:flex;}@media not (pointer:coarse){.example-wrap:hover>a.test-arrow,.example-wrap:hover>.button-holder{visibility:visible;}}.example-wrap .button-holder.keep-visible{visibility:visible;}.example-wrap .button-holder>*{background:var(--main-background-color);cursor:pointer;border-radius:var(--button-border-radius);height:var(--copy-path-height);width:var(--copy-path-width);border:0;color:var(--code-example-button-color);}.example-wrap .button-holder>*:hover{color:var(--code-example-button-hover-color);}.example-wrap .button-holder>*:not(:first-child){margin-left:var(--button-left-margin);}.example-wrap .button-holder .copy-button{padding:2px 0 0 4px;}.example-wrap .button-holder .copy-button::before,.example-wrap .test-arrow::before{filter:var(--copy-path-img-filter);}.example-wrap .button-holder .copy-button::before{content:var(--clipboard-image);}.example-wrap .button-holder .copy-button:hover::before,.example-wrap .test-arrow:hover::before{filter:var(--copy-path-img-hover-filter);}.example-wrap .button-holder .copy-button.clicked::before{content:var(--checkmark-image);padding-right:5px;}.code-attribute{font-weight:300;color:var(--code-attribute-color);}.item-spacer{width:100%;height:12px;display:block;}.main-heading span.since::before{content:"Since ";}.sub-variant h4{font-size:1rem;font-weight:400;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}@keyframes targetfadein{from{background-color:var(--main-background-color);}10%{background-color:var(--target-border-color);}to{background-color:var(--target-background-color);}}:target{padding-right:3px;background-color:var(--target-background-color);border-right:3px solid var(--target-border-color);}.code-header a.tooltip{color:inherit;margin-right:15px;position:relative;}.code-header a.tooltip:hover{color:var(--link-color);}a.tooltip:hover::after{position:absolute;top:calc(100% - 10px);left:-15px;right:-15px;height:20px;content:"\00a0";}@media not (prefers-reduced-motion){:target{animation:0.65s cubic-bezier(0,0,0.1,1.0) 0.1s targetfadein;}.fade-out{opacity:0;transition:opacity 0.45s cubic-bezier(0,0,0.1,1.0);}}.popover.tooltip .content{margin:0.25em 0.5em;}.popover.tooltip .content pre,.popover.tooltip .content code{background:transparent;margin:0;padding:0;font-size:1.25rem;white-space:pre-wrap;}.popover.tooltip .content>h3:first-child{margin:0 0 5px 0;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#search-tabs{margin-top:0.25rem;display:flex;flex-direction:row;gap:1px;margin-bottom:4px;}#search-tabs button{text-align:center;font-size:1.125rem;border:0;border-top:2px solid;flex:1;line-height:1.5;color:inherit;}#search-tabs button:not(.selected){background-color:var(--search-tab-button-not-selected-background);border-top-color:var(--search-tab-button-not-selected-border-top-color);}#search-tabs button:hover,#search-tabs button.selected{background-color:var(--search-tab-button-selected-background);border-top-color:var(--search-tab-button-selected-border-top-color);}#search-tabs .count{font-size:1rem;font-variant-numeric:tabular-nums;color:var(--search-tab-title-count-color);}#search .error code{border-radius:3px;background-color:var(--search-error-code-background-color);}.search-corrections{font-weight:normal;}#src-sidebar{width:100%;overflow:auto;}#src-sidebar div.files>a:hover,details.dir-entry summary:hover,#src-sidebar div.files>a:focus,details.dir-entry summary:focus{background-color:var(--src-sidebar-background-hover);}#src-sidebar div.files>a.selected{background-color:var(--src-sidebar-background-selected);}.src-sidebar-title{position:sticky;top:0;display:flex;padding:8px 8px 0 48px;margin-bottom:7px;background:var(--sidebar-background-color);border-bottom:1px solid var(--border-color);}#settings-menu,#help-button,button#toggle-all-docs{margin-left:var(--button-left-margin);display:flex;line-height:1.25;}#sidebar-button{display:none;line-height:0;}.hide-sidebar #sidebar-button,.src #sidebar-button{display:flex;margin-right:4px;position:fixed;left:6px;height:34px;width:34px;background-color:var(--main-background-color);z-index:1;}.src #sidebar-button{left:8px;z-index:calc(var(--desktop-sidebar-z-index) + 1);}.hide-sidebar .src #sidebar-button{position:static;}#settings-menu>a,#help-button>a,#sidebar-button>a,button#toggle-all-docs{display:flex;align-items:center;justify-content:center;flex-direction:column;border:1px solid transparent;border-radius:var(--button-border-radius);color:var(--main-color);}#settings-menu>a,#help-button>a,button#toggle-all-docs{width:80px;border-radius:var(--toolbar-button-border-radius);}#sidebar-button>a{background-color:var(--button-background-color);border-color:var(--border-color);width:33px;}#settings-menu>a:hover,#settings-menu>a:focus-visible,#help-button>a:hover,#help-button>a:focus-visible,#sidebar-button>a:hover,#sidebar-button>a:focus-visible,button#toggle-all-docs:hover,button#toggle-all-docs:focus-visible{border-color:var(--settings-button-border-focus);text-decoration:none;}#settings-menu>a:before{content:url('data:image/svg+xml,\ + ');width:18px;height:18px;filter:var(--settings-menu-filter);}button#toggle-all-docs:before{content:url('data:image/svg+xml,\ + ');width:18px;height:18px;filter:var(--settings-menu-filter);}#help-button>a:before{content:url('data:image/svg+xml,\ + \ + ?');width:18px;height:18px;filter:var(--settings-menu-filter);}button#toggle-all-docs:before,#help-button>a:before,#settings-menu>a:before{filter:var(--settings-menu-filter);margin:8px;}@media not (pointer:coarse){button#toggle-all-docs:hover:before,#help-button>a:hover:before,#settings-menu>a:hover:before{filter:var(--settings-menu-hover-filter);}}button[disabled]#toggle-all-docs{opacity:0.25;border:solid 1px var(--main-background-color);background-size:cover;}button[disabled]#toggle-all-docs:hover{border:solid 1px var(--main-background-color);cursor:not-allowed;}rustdoc-toolbar span.label{font-size:1rem;flex-grow:1;padding-bottom:4px;}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}#copy-path{color:var(--copy-path-button-color);background:var(--main-background-color);height:var(--copy-path-height);width:var(--copy-path-width);margin-left:10px;padding:0;padding-left:2px;border:0;font-size:0;}#copy-path::before{filter:var(--copy-path-img-filter);content:var(--clipboard-image);}#copy-path:hover::before{filter:var(--copy-path-img-hover-filter);}#copy-path.clicked::before{content:var(--checkmark-image);}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px var(--border-color);border-radius:3px;color:var(--kbd-color);background-color:var(--kbd-background);box-shadow:inset 0 -1px 0 var(--kbd-box-shadow-color);}ul.all-items>li{list-style:none;}details.dir-entry{padding-left:4px;}details.dir-entry>summary{margin:0 0 0 -4px;padding:0 0 0 4px;cursor:pointer;}details.dir-entry div.folders,details.dir-entry div.files{padding-left:23px;}details.dir-entry a{display:block;}details.toggle{contain:layout;position:relative;}details.big-toggle{contain:inline-size;}details.toggle>summary.hideme{cursor:pointer;font-size:1rem;}details.toggle>summary{list-style:none;outline:none;}details.toggle>summary::-webkit-details-marker,details.toggle>summary::marker{display:none;}details.toggle>summary.hideme>span{margin-left:9px;}details.toggle>summary::before{background:url('data:image/svg+xml,\ + ');content:"";cursor:pointer;width:16px;height:16px;display:inline-block;vertical-align:middle;opacity:.5;filter:var(--toggle-filter);}details.toggle>summary.hideme>span,.more-examples-toggle summary,.more-examples-toggle .hide-more{color:var(--toggles-color);}details.toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.toggle>summary.hideme::after{content:"";}details.toggle>summary:focus::before,details.toggle>summary:hover::before{opacity:1;}details.toggle>summary:focus-visible::before{outline:1px dotted #000;outline-offset:1px;}details.non-exhaustive{margin-bottom:8px;}details.toggle>summary.hideme::before{position:relative;}details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;top:4px;}.impl-items>details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;}details.big-toggle>summary:not(.hideme)::before{left:-34px;top:9px;}details.toggle[open] >summary.hideme{position:absolute;}details.toggle[open] >summary.hideme>span{display:none;}details.toggle[open] >summary::before{background:url('data:image/svg+xml,\ + ');}details.toggle[open] >summary::after{content:"Collapse";}.docblock summary>*{display:inline-block;}.docblock>.example-wrap:first-child .tooltip{margin-top:16px;}.src #sidebar-button>a:before,.sidebar-menu-toggle:before{content:url('data:image/svg+xml,\ + ');opacity:0.75;}.sidebar-menu-toggle:hover:before,.sidebar-menu-toggle:active:before,.sidebar-menu-toggle:focus:before{opacity:1;}.src #sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');opacity:0.75;}@media (max-width:850px){#search-tabs .count{display:block;}.side-by-side{flex-direction:column-reverse;}.side-by-side>div{width:auto;}}@media (max-width:700px){*[id]{scroll-margin-top:45px;}#copy-path{display:none;}rustdoc-toolbar span.label{display:none;}#settings-menu>a,#help-button>a,button#toggle-all-docs{width:33px;}#settings.popover{--popover-arrow-offset:86px;}#help.popover{--popover-arrow-offset:48px;}.rustdoc{display:block;}main{padding-left:15px;padding-top:0px;}.sidebar .logo-container,.sidebar .location,.sidebar-resizer{display:none;}.sidebar{position:fixed;top:45px;left:-1000px;z-index:11;height:calc(100vh - 45px);width:200px;}.src main,.rustdoc.src .sidebar{top:0;padding:0;height:100vh;border:0;}.src .search-form{margin-left:40px;}.src .main-heading{margin-left:8px;}.hide-sidebar .search-form{margin-left:32px;}.hide-sidebar .src .search-form{margin-left:0;}.sidebar.shown,.src-sidebar-expanded .src .sidebar,.rustdoc:not(.src) .sidebar:focus-within{left:0;}.mobile-topbar h2{padding-bottom:0;margin:auto 0.5em auto auto;overflow:hidden;font-size:24px;white-space:nowrap;text-overflow:ellipsis;}.mobile-topbar .logo-container>img{max-width:35px;max-height:35px;margin:5px 0 5px 20px;}.mobile-topbar{display:flex;flex-direction:row;position:sticky;z-index:10;font-size:2rem;height:45px;width:100%;left:0;top:0;}.hide-sidebar .mobile-topbar{display:none;}.sidebar-menu-toggle{width:45px;border:none;line-height:0;}.hide-sidebar .sidebar-menu-toggle{display:none;}.sidebar-elems{margin-top:1em;}.anchor{display:none !important;}#main-content>details.toggle>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}.sidebar-menu-toggle:before{filter:var(--mobile-sidebar-menu-filter);}.sidebar-menu-toggle:hover{background:var(--main-background-color);}.item-table,.item-row,.item-table>li,.item-table>li>div,.search-results>a,.search-results>a>div{display:block;}.search-results>a{padding:5px 0px;}.search-results>a>div.desc,.item-table>li>div.desc{padding-left:2em;}.search-results .result-name{display:block;}.search-results .result-name .typename{width:initial;margin-right:0;}.search-results .result-name .typename,.search-results .result-name .path{display:inline;}.src-sidebar-expanded .src .sidebar{position:fixed;max-width:100vw;width:100vw;}.src .src-sidebar-title{padding-top:0;}details.toggle:not(.top-doc)>summary{margin-left:10px;}.impl-items>details.toggle>summary:not(.hideme)::before,#main-content>details.toggle:not(.top-doc)>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}.impl-items>.item-info{margin-left:34px;}.src nav.sub{margin:0 0 -25px 0;padding:var(--nav-sub-mobile-padding);}}@media (min-width:701px){.scraped-example-title{position:absolute;z-index:10;background:var(--main-background-color);bottom:8px;right:5px;padding:2px 4px;box-shadow:0 0 4px var(--main-background-color);}.item-table>li>.item-name{width:33%;}.item-table>li>div{overflow-wrap:anywhere;}}@media print{nav.sidebar,nav.sub,.out-of-band,a.src,#copy-path,details.toggle[open] >summary::before,details.toggle>summary::before,details.toggle.top-doc>summary{display:none;}.docblock{margin-left:0;}main{padding:10px;}}@media (max-width:464px){.docblock{margin-left:12px;}.docblock code{overflow-wrap:break-word;overflow-wrap:anywhere;}nav.sub{flex-direction:column;}.search-form{align-self:stretch;}}.variant,.implementors-toggle>summary,.impl,#implementors-list>.docblock,.impl-items>section,.impl-items>.toggle>summary,.methods>section,.methods>.toggle>summary{margin-bottom:0.75em;}.variants>.docblock,.implementors-toggle>.docblock,.impl-items>.toggle[open]:not(:last-child),.methods>.toggle[open]:not(:last-child),.implementors-toggle[open]:not(:last-child){margin-bottom:2em;}#trait-implementations-list .impl-items>.toggle:not(:last-child),#synthetic-implementations-list .impl-items>.toggle:not(:last-child),#blanket-implementations-list .impl-items>.toggle:not(:last-child){margin-bottom:1em;}.scraped-example-list .scrape-help{margin-left:10px;padding:0 4px;font-weight:normal;font-size:12px;position:relative;bottom:1px;border:1px solid var(--scrape-example-help-border-color);border-radius:50px;color:var(--scrape-example-help-color);}.scraped-example-list .scrape-help:hover{border-color:var(--scrape-example-help-hover-border-color);color:var(--scrape-example-help-hover-color);}.scraped-example:not(.expanded) .example-wrap::before,.scraped-example:not(.expanded) .example-wrap::after{content:" ";width:100%;height:5px;position:absolute;z-index:1;}.scraped-example:not(.expanded) .example-wrap::before{top:0;background:linear-gradient(to bottom,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example:not(.expanded) .example-wrap::after{bottom:0;background:linear-gradient(to top,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example:not(.expanded){width:100%;overflow-y:hidden;margin-bottom:0;}.scraped-example:not(.expanded){overflow-x:hidden;}.scraped-example .rust span.highlight{background:var(--scrape-example-code-line-highlight);}.scraped-example .rust span.highlight.focus{background:var(--scrape-example-code-line-highlight-focus);}.more-examples-toggle{max-width:calc(100% + 25px);margin-top:10px;margin-left:-25px;}.more-examples-toggle .hide-more{margin-left:25px;cursor:pointer;}.more-scraped-examples{margin-left:25px;position:relative;}.toggle-line{position:absolute;top:5px;bottom:0;right:calc(100% + 10px);padding:0 4px;cursor:pointer;}.toggle-line-inner{min-width:2px;height:100%;background:var(--scrape-example-toggle-line-background);}.toggle-line:hover .toggle-line-inner{background:var(--scrape-example-toggle-line-hover-background);}.more-scraped-examples .scraped-example,.example-links{margin-top:20px;}.more-scraped-examples .scraped-example:first-child{margin-top:5px;}.example-links ul{margin-bottom:0;}:root[data-theme="light"],:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#595959;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="dark"]{--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--code-example-button-color:#7f7f7f;--code-example-button-hover-color:#a5a5a5;--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--settings-menu-filter:invert(50%);--settings-menu-hover-filter:invert(65%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="ayu"]{--main-background-color:#0f1419;--main-color:#c5c5c5;--settings-input-color:#ffb454;--settings-input-border-color:#999;--settings-button-color:#fff;--settings-button-border-focus:#e0e0e0;--sidebar-background-color:#14191f;--sidebar-background-color-hover:rgba(70,70,70,0.33);--code-block-background-color:#191f26;--scrollbar-track-background-color:transparent;--scrollbar-thumb-background-color:#5c6773;--scrollbar-color:#5c6773 #24292f;--headings-border-bottom-color:#5c6773;--border-color:#5c6773;--button-background-color:#141920;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#5c6773;--copy-path-button-color:#fff;--copy-path-img-filter:invert(70%);--copy-path-img-hover-filter:invert(100%);--code-example-button-color:#b2b2b2;--code-example-button-hover-color:#fff;--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ffa0a5;--trait-link-color:#39afd7;--assoc-item-link-color:#39afd7;--function-link-color:#fdd687;--macro-link-color:#a37acc;--keyword-link-color:#39afd7;--mod-link-color:#39afd7;--link-color:#39afd7;--sidebar-link-color:#53b1db;--sidebar-current-link-background-color:transparent;--search-result-link-focus-background-color:#3c3c3c;--search-result-border-color:#aaa3;--search-color:#fff;--search-error-code-background-color:#4f4c4c;--search-results-alias-color:#c5c5c5;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:none;--search-tab-button-not-selected-background:transparent !important;--search-tab-button-selected-border-top-color:none;--search-tab-button-selected-background:#141920 !important;--settings-menu-filter:invert(70%);--settings-menu-hover-filter:invert(100%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ff7733;--code-highlight-kw-2-color:#ff7733;--code-highlight-lifetime-color:#ff7733;--code-highlight-prelude-color:#69f2df;--code-highlight-prelude-val-color:#ff7733;--code-highlight-number-color:#b8cc52;--code-highlight-string-color:#b8cc52;--code-highlight-literal-color:#ff7733;--code-highlight-attribute-color:#e6e1cf;--code-highlight-self-color:#36a3d9;--code-highlight-macro-color:#a37acc;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#788797;--code-highlight-doc-comment-color:#a1ac88;--src-line-numbers-span-color:#5c6773;--src-line-number-highlighted-background-color:rgba(255,236,164,0.06);--target-background-color:rgba(255,236,164,0.06);--target-border-color:rgba(255,180,76,0.85);--kbd-color:#c5c5c5;--kbd-background:#314559;--kbd-box-shadow-color:#5c6773;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) brightness(94%) contrast(94%);--crate-search-div-hover-filter:invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%);--crate-search-hover-border:#e0e0e0;--src-sidebar-background-selected:#14191f;--src-sidebar-background-hover:#14191f;--table-alt-row-background-color:#191f26;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(15,20,25,1);--scrape-example-code-wrapper-background-end:rgba(15,20,25,0);--sidebar-resizer-hover:hsl(34,50%,33%);--sidebar-resizer-active:hsl(34,100%,66%);}:root[data-theme="ayu"] h1,:root[data-theme="ayu"] h2,:root[data-theme="ayu"] h3,:root[data-theme="ayu"] h4,:where(:root[data-theme="ayu"]) h1 a,:root[data-theme="ayu"] .sidebar h2 a,:root[data-theme="ayu"] .sidebar h3 a{color:#fff;}:root[data-theme="ayu"] .docblock code{color:#ffb454;}:root[data-theme="ayu"] .docblock a>code{color:#39AFD7 !important;}:root[data-theme="ayu"] .code-header,:root[data-theme="ayu"] .docblock pre>code,:root[data-theme="ayu"] pre,:root[data-theme="ayu"] pre>code,:root[data-theme="ayu"] .item-info code,:root[data-theme="ayu"] .rustdoc.source .example-wrap{color:#e6e1cf;}:root[data-theme="ayu"] .sidebar .current,:root[data-theme="ayu"] .sidebar .current a,:root[data-theme="ayu"] .sidebar a:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:hover,:root[data-theme="ayu"] details.dir-entry summary:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:focus,:root[data-theme="ayu"] details.dir-entry summary:focus,:root[data-theme="ayu"] #src-sidebar div.files>a.selected{color:#ffb44c;}:root[data-theme="ayu"] .sidebar-elems .location{color:#ff7733;}:root[data-theme="ayu"] .src-line-numbers .line-highlighted{color:#708090;padding-right:7px;border-right:1px solid #ffb44c;}:root[data-theme="ayu"] .search-results a:hover,:root[data-theme="ayu"] .search-results a:focus{color:#fff !important;background-color:#3c3c3c;}:root[data-theme="ayu"] .search-results a{color:#0096cf;}:root[data-theme="ayu"] .search-results a div.desc{color:#c5c5c5;}:root[data-theme="ayu"] .result-name .primitive>i,:root[data-theme="ayu"] .result-name .keyword>i{color:#788797;}:root[data-theme="ayu"] #search-tabs>button.selected{border-bottom:1px solid #ffb44c !important;border-top:none;}:root[data-theme="ayu"] #search-tabs>button:not(.selected){border:none;background-color:transparent !important;}:root[data-theme="ayu"] #search-tabs>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}:root[data-theme="ayu"] #settings-menu>a img,:root[data-theme="ayu"] #sidebar-button>a:before{filter:invert(100);} \ No newline at end of file diff --git a/static.files/scrape-examples-46fc985aa763a438.js b/static.files/scrape-examples-46fc985aa763a438.js new file mode 100644 index 00000000..87b6065d --- /dev/null +++ b/static.files/scrape-examples-46fc985aa763a438.js @@ -0,0 +1 @@ +"use strict";(function(){const DEFAULT_MAX_LINES=5;const HIDDEN_MAX_LINES=10;function scrollToLoc(elt,loc,isHidden){const lines=elt.querySelector(".src-line-numbers > pre");let scrollOffset;const maxLines=isHidden?HIDDEN_MAX_LINES:DEFAULT_MAX_LINES;if(loc[1]-loc[0]>maxLines){const line=Math.max(0,loc[0]-1);scrollOffset=lines.children[line].offsetTop}else{const halfHeight=elt.offsetHeight/2;const offsetTop=lines.children[loc[0]].offsetTop;const lastLine=lines.children[loc[1]];const offsetBot=lastLine.offsetTop+lastLine.offsetHeight;const offsetMid=(offsetTop+offsetBot)/2;scrollOffset=offsetMid-halfHeight}lines.parentElement.scrollTo(0,scrollOffset);elt.querySelector(".rust").scrollTo(0,scrollOffset)}function createScrapeButton(parent,className,content){const button=document.createElement("button");button.className=className;button.innerText=content;parent.insertBefore(button,parent.firstChild);return button}window.updateScrapedExample=(example,buttonHolder)=>{let locIndex=0;const highlights=Array.prototype.slice.call(example.querySelectorAll(".highlight"));const link=example.querySelector(".scraped-example-title a");let expandButton=null;if(!example.classList.contains("expanded")){expandButton=createScrapeButton(buttonHolder,"expand","↕")}const isHidden=example.parentElement.classList.contains("more-scraped-examples");const locs=example.locs;if(locs.length>1){const next=createScrapeButton(buttonHolder,"next","≻");const prev=createScrapeButton(buttonHolder,"prev","≺");const onChangeLoc=changeIndex=>{removeClass(highlights[locIndex],"focus");changeIndex();scrollToLoc(example,locs[locIndex][0],isHidden);addClass(highlights[locIndex],"focus");const url=locs[locIndex][1];const title=locs[locIndex][2];link.href=url;link.innerHTML=title};prev.addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex-1+locs.length)%locs.length})});next.addEventListener("click",()=>{onChangeLoc(()=>{locIndex=(locIndex+1)%locs.length})})}if(expandButton){expandButton.addEventListener("click",()=>{if(hasClass(example,"expanded")){removeClass(example,"expanded");scrollToLoc(example,locs[0][0],isHidden)}else{addClass(example,"expanded")}})}};function setupLoc(example,isHidden){example.locs=JSON.parse(example.attributes.getNamedItem("data-locs").textContent);scrollToLoc(example,example.locs[0][0],isHidden)}const firstExamples=document.querySelectorAll(".scraped-example-list > .scraped-example");onEachLazy(firstExamples,el=>setupLoc(el,false));onEachLazy(document.querySelectorAll(".more-examples-toggle"),toggle=>{onEachLazy(toggle.querySelectorAll(".toggle-line, .hide-more"),button=>{button.addEventListener("click",()=>{toggle.open=false})});const moreExamples=toggle.querySelectorAll(".scraped-example");toggle.querySelector("summary").addEventListener("click",()=>{setTimeout(()=>{onEachLazy(moreExamples,el=>setupLoc(el,true))})},{once:true})})})() \ No newline at end of file diff --git a/static.files/search-e056c65ede92db13.js b/static.files/search-e056c65ede92db13.js new file mode 100644 index 00000000..3e2c702e --- /dev/null +++ b/static.files/search-e056c65ede92db13.js @@ -0,0 +1,6 @@ +"use strict";if(!Array.prototype.toSpliced){Array.prototype.toSpliced=function(){const me=this.slice();Array.prototype.splice.apply(me,arguments);return me}}(function(){const itemTypes=["keyword","primitive","mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","associatedtype","constant","associatedconstant","union","foreigntype","existential","attr","derive","traitalias","generic",];const TY_GENERIC=itemTypes.indexOf("generic");const TY_IMPORT=itemTypes.indexOf("import");const ROOT_PATH=typeof window!=="undefined"?window.rootPath:"../";const UNBOXING_LIMIT=5;const REGEX_IDENT=/\p{ID_Start}\p{ID_Continue}*|_\p{ID_Continue}+/uy;const REGEX_INVALID_TYPE_FILTER=/[^a-z]/ui;const MAX_RESULTS=200;const NO_TYPE_FILTER=-1;const editDistanceState={current:[],prev:[],prevPrev:[],calculate:function calculate(a,b,limit){if(a.lengthlimit){return limit+1}while(b.length>0&&b[0]===a[0]){a=a.substring(1);b=b.substring(1)}while(b.length>0&&b[b.length-1]===a[a.length-1]){a=a.substring(0,a.length-1);b=b.substring(0,b.length-1)}if(b.length===0){return minDist}const aLength=a.length;const bLength=b.length;for(let i=0;i<=bLength;++i){this.current[i]=0;this.prev[i]=i;this.prevPrev[i]=Number.MAX_VALUE}for(let i=1;i<=aLength;++i){this.current[0]=i;const aIdx=i-1;for(let j=1;j<=bLength;++j){const bIdx=j-1;const substitutionCost=a[aIdx]===b[bIdx]?0:1;this.current[j]=Math.min(this.prev[j]+1,this.current[j-1]+1,this.prev[j-1]+substitutionCost,);if((i>1)&&(j>1)&&(a[aIdx]===b[bIdx-1])&&(a[aIdx-1]===b[bIdx])){this.current[j]=Math.min(this.current[j],this.prevPrev[j-2]+1,)}}const prevPrevTmp=this.prevPrev;this.prevPrev=this.prev;this.prev=this.current;this.current=prevPrevTmp}const distance=this.prev[bLength];return distance<=limit?distance:(limit+1)},};function editDistance(a,b,limit){return editDistanceState.calculate(a,b,limit)}function isEndCharacter(c){return"=,>-])".indexOf(c)!==-1}function isSeparatorCharacter(c){return c===","||c==="="}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function skipWhitespace(parserState){while(parserState.pos0){const c=parserState.userQuery[pos-1];if(c===lookingFor){return true}else if(c!==" "){break}pos-=1}return false}function isLastElemGeneric(elems,parserState){return(elems.length>0&&elems[elems.length-1].generics.length>0)||prevIs(parserState,">")}function getFilteredNextElem(query,parserState,elems,isInGenerics){const start=parserState.pos;if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){throw["Expected type filter before ",":"]}getNextElem(query,parserState,elems,isInGenerics);if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}if(elems.length===0){throw["Expected type filter before ",":"]}else if(query.literalSearch){throw["Cannot use quotes on type filter"]}const typeFilterElem=elems.pop();checkExtraTypeFilterCharacters(start,parserState);parserState.typeFilter=typeFilterElem.name;parserState.pos+=1;parserState.totalElems-=1;query.literalSearch=false;getNextElem(query,parserState,elems,isInGenerics)}}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;let foundSeparator=false;const oldTypeFilter=parserState.typeFilter;parserState.typeFilter=null;const oldIsInBinding=parserState.isInBinding;parserState.isInBinding=null;let hofParameters=null;let extra="";if(endChar===">"){extra="<"}else if(endChar==="]"){extra="["}else if(endChar===")"){extra="("}else if(endChar===""){extra="->"}else{extra=endChar}while(parserState.pos"," after ","="]}hofParameters=[...elems];elems.length=0;parserState.pos+=2;foundStopChar=true;foundSeparator=false;continue}else if(c===" "){parserState.pos+=1;continue}else if(isSeparatorCharacter(c)){parserState.pos+=1;foundStopChar=true;foundSeparator=true;continue}else if(c===":"&&isPathStart(parserState)){throw["Unexpected ","::",": paths cannot start with ","::"]}else if(isEndCharacter(c)){throw["Unexpected ",c," after ",extra]}if(!foundStopChar){let extra=[];if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(endChar!==""){throw["Expected ",",",", ","=",", or ",endChar,...extra,", found ",c,]}throw["Expected ",","," or ","=",...extra,", found ",c,]}const posBefore=parserState.pos;getFilteredNextElem(query,parserState,elems,endChar!=="");if(endChar!==""&&parserState.pos>=parserState.length){throw["Unclosed ",extra]}if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}if(parserState.pos>=parserState.length&&endChar!==""){throw["Unclosed ",extra]}parserState.pos+=1;if(hofParameters){foundSeparator=false;if([...elems,...hofParameters].some(x=>x.bindingName)||parserState.isInBinding){throw["Unexpected ","="," within ","->"]}const hofElem=makePrimitiveElement("->",{generics:hofParameters,bindings:new Map([["output",[...elems]]]),typeFilter:null,});elems.length=0;elems[0]=hofElem}parserState.typeFilter=oldTypeFilter;parserState.isInBinding=oldIsInBinding;return{foundSeparator}}function getNextElem(query,parserState,elems,isInGenerics){const generics=[];skipWhitespace(parserState);let start=parserState.pos;let end;if("[(".indexOf(parserState.userQuery[parserState.pos])!==-1){let endChar=")";let name="()";let friendlyName="tuple";if(parserState.userQuery[parserState.pos]==="["){endChar="]";name="[]";friendlyName="slice"}parserState.pos+=1;const{foundSeparator}=getItemsBefore(query,parserState,generics,endChar);const typeFilter=parserState.typeFilter;const bindingName=parserState.isInBinding;parserState.typeFilter=null;parserState.isInBinding=null;for(const gen of generics){if(gen.bindingName!==null){throw["Type parameter ","=",` cannot be within ${friendlyName} `,name]}}if(name==="()"&&!foundSeparator&&generics.length===1&&typeFilter===null){elems.push(generics[0])}else if(name==="()"&&generics.length===1&&generics[0].name==="->"){generics[0].typeFilter=typeFilter;elems.push(generics[0])}else{if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive ",name," and ",typeFilter," both specified",]}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}elems.push(makePrimitiveElement(name,{bindingName,generics}))}}else if(parserState.userQuery[parserState.pos]==="&"){if(parserState.typeFilter!==null&&parserState.typeFilter!=="primitive"){throw["Invalid search type: primitive ","&"," and ",parserState.typeFilter," both specified",]}parserState.typeFilter=null;parserState.pos+=1;let c=parserState.userQuery[parserState.pos];while(c===" "&&parserState.pos=end){throw["Found generics without a path"]}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}else if(parserState.pos=end){throw["Found generics without a path"]}if(parserState.isInBinding){throw["Unexpected ","("," after ","="]}parserState.pos+=1;const typeFilter=parserState.typeFilter;parserState.typeFilter=null;getItemsBefore(query,parserState,generics,")");skipWhitespace(parserState);if(isReturnArrow(parserState)){parserState.pos+=2;skipWhitespace(parserState);getFilteredNextElem(query,parserState,generics,isInGenerics);generics[generics.length-1].bindingName=makePrimitiveElement("output")}else{generics.push(makePrimitiveElement(null,{bindingName:makePrimitiveElement("output"),typeFilter:null,}))}parserState.typeFilter=typeFilter}if(isStringElem){skipWhitespace(parserState)}if(start>=end&&generics.length===0){return}if(parserState.userQuery[parserState.pos]==="="){if(parserState.isInBinding){throw["Cannot write ","="," twice in a binding"]}if(!isInGenerics){throw["Type parameter ","="," must be within generics list"]}const name=parserState.userQuery.slice(start,end).trim();if(name==="!"){throw["Type parameter ","="," key cannot be ","!"," never type"]}if(name.includes("!")){throw["Type parameter ","="," key cannot be ","!"," macro"]}if(name.includes("::")){throw["Type parameter ","="," key cannot contain ","::"," path"]}if(name.includes(":")){throw["Type parameter ","="," key cannot contain ",":"," type"]}parserState.isInBinding={name,generics}}else{elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics,),)}}}function checkExtraTypeFilterCharacters(start,parserState){const query=parserState.userQuery.slice(start,parserState.pos).trim();const match=query.match(REGEX_INVALID_TYPE_FILTER);if(match){throw["Unexpected ",match[0]," in type filter (before ",":",")",]}}function createQueryElement(query,parserState,name,generics,isInGenerics){const path=name.trim();if(path.length===0&&generics.length===0){throw["Unexpected ",parserState.userQuery[parserState.pos]]}if(query.literalSearch&&parserState.totalElems-parserState.genericsElems>0){throw["Cannot have more than one element if you use quotes"]}const typeFilter=parserState.typeFilter;parserState.typeFilter=null;if(name.trim()==="!"){if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive never type ","!"," and ",typeFilter," both specified",]}if(generics.length!==0){throw["Never type ","!"," does not accept generic parameters",]}const bindingName=parserState.isInBinding;parserState.isInBinding=null;return makePrimitiveElement("never",{bindingName})}const quadcolon=/::\s*::/.exec(path);if(path.startsWith("::")){throw["Paths cannot start with ","::"]}else if(path.endsWith("::")){throw["Paths cannot end with ","::"]}else if(quadcolon!==null){throw["Unexpected ",quadcolon[0]]}const pathSegments=path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/);if(pathSegments.length===0||(pathSegments.length===1&&pathSegments[0]==="")){if(generics.length>0||prevIs(parserState,">")){throw["Found generics without a path"]}else{throw["Unexpected ",parserState.userQuery[parserState.pos]]}}for(const[i,pathSegment]of pathSegments.entries()){if(pathSegment==="!"){if(i!==0){throw["Never type ","!"," is not associated item"]}pathSegments[i]="never"}}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}const bindingName=parserState.isInBinding;parserState.isInBinding=null;const bindings=new Map();const pathLast=pathSegments[pathSegments.length-1];return{name:name.trim(),id:null,fullPath:pathSegments,pathWithoutLast:pathSegments.slice(0,pathSegments.length-1),pathLast,normalizedPathLast:pathLast.replace(/_/g,""),generics:generics.filter(gen=>{if(gen.bindingName!==null){if(gen.name!==null){gen.bindingName.generics.unshift(gen)}bindings.set(gen.bindingName.name,gen.bindingName.generics);return false}return true}),bindings,typeFilter,bindingName,}}function makePrimitiveElement(name,extra){return Object.assign({name,id:null,fullPath:[name],pathWithoutLast:[],pathLast:name,normalizedPathLast:name,generics:[],bindings:new Map(),typeFilter:"primitive",bindingName:null,},extra)}function getStringElem(query,parserState,isInGenerics){if(isInGenerics){throw["Unexpected ","\""," in generics"]}else if(query.literalSearch){throw["Cannot have more than one literal search element"]}else if(parserState.totalElems-parserState.genericsElems>0){throw["Cannot use literal search when there is more than one element"]}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw["Unclosed ","\""]}else if(parserState.userQuery[end]!=="\""){throw["Unexpected ",parserState.userQuery[end]," in a string element"]}else if(start===end){throw["Cannot have empty string element"]}parserState.pos+=1;query.literalSearch=true}function getIdentEndPosition(parserState){let afterIdent=consumeIdent(parserState);let end=parserState.pos;let macroExclamation=-1;while(parserState.pos0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]," (not a valid identifier)"]}else{throw["Unexpected ",c," (not a valid identifier)"]}parserState.pos+=1;afterIdent=consumeIdent(parserState);end=parserState.pos}if(macroExclamation!==-1){if(parserState.typeFilter===null){parserState.typeFilter="macro"}else if(parserState.typeFilter!=="macro"){throw["Invalid search type: macro ","!"," and ",parserState.typeFilter," both specified",]}end=macroExclamation}return end}function isSpecialStartCharacter(c){return"<\"".indexOf(c)!==-1}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function consumeIdent(parserState){REGEX_IDENT.lastIndex=parserState.pos;const match=parserState.userQuery.match(REGEX_IDENT);if(match){parserState.pos+=match[0].length;return true}return false}function isPathSeparator(c){return c===":"||c===" "}class VlqHexDecoder{constructor(string,cons){this.string=string;this.cons=cons;this.offset=0;this.backrefQueue=[]}decodeList(){let c=this.string.charCodeAt(this.offset);const ret=[];while(c!==125){ret.push(this.decode());c=this.string.charCodeAt(this.offset)}this.offset+=1;return ret}decode(){let n=0;let c=this.string.charCodeAt(this.offset);if(c===123){this.offset+=1;return this.decodeList()}while(c<96){n=(n<<4)|(c&0xF);this.offset+=1;c=this.string.charCodeAt(this.offset)}n=(n<<4)|(c&0xF);const[sign,value]=[n&1,n>>1];this.offset+=1;return sign?-value:value}next(){const c=this.string.charCodeAt(this.offset);if(c>=48&&c<64){this.offset+=1;return this.backrefQueue[c-48]}if(c===96){this.offset+=1;return this.cons(0)}const result=this.cons(this.decode());this.backrefQueue.unshift(result);if(this.backrefQueue.length>16){this.backrefQueue.pop()}return result}}class RoaringBitmap{constructor(str){const strdecoded=atob(str);const u8array=new Uint8Array(strdecoded.length);for(let j=0;j=4){offsets=[];for(let j=0;j>3]&(1<<(j&0x7))){const runcount=(u8array[i]|(u8array[i+1]<<8));i+=2;this.containers.push(new RoaringBitmapRun(runcount,u8array.slice(i,i+(runcount*4)),));i+=runcount*4}else if(this.cardinalities[j]>=4096){this.containers.push(new RoaringBitmapBits(u8array.slice(i,i+8192)));i+=8192}else{const end=this.cardinalities[j]*2;this.containers.push(new RoaringBitmapArray(this.cardinalities[j],u8array.slice(i,i+end),));i+=end}}}contains(keyvalue){const key=keyvalue>>16;const value=keyvalue&0xFFFF;for(let i=0;i=start&&value<=(start+lenm1)){return true}}return false}}class RoaringBitmapArray{constructor(cardinality,array){this.cardinality=cardinality;this.array=array}contains(value){const l=this.cardinality*2;for(let i=0;i>3]&(1<<(value&7)))}}class DocSearch{constructor(rawSearchIndex,rootPath,searchState){this.searchIndexDeprecated=new Map();this.searchIndexEmptyDesc=new Map();this.functionTypeFingerprint=null;this.typeNameIdMap=new Map();this.ALIASES=new Map();this.rootPath=rootPath;this.searchState=searchState;this.typeNameIdOfArray=this.buildTypeMapIndex("array");this.typeNameIdOfSlice=this.buildTypeMapIndex("slice");this.typeNameIdOfArrayOrSlice=this.buildTypeMapIndex("[]");this.typeNameIdOfTuple=this.buildTypeMapIndex("tuple");this.typeNameIdOfUnit=this.buildTypeMapIndex("unit");this.typeNameIdOfTupleOrUnit=this.buildTypeMapIndex("()");this.typeNameIdOfFn=this.buildTypeMapIndex("fn");this.typeNameIdOfFnMut=this.buildTypeMapIndex("fnmut");this.typeNameIdOfFnOnce=this.buildTypeMapIndex("fnonce");this.typeNameIdOfHof=this.buildTypeMapIndex("->");this.EMPTY_BINDINGS_MAP=new Map();this.EMPTY_GENERICS_ARRAY=[];this.TYPES_POOL=new Map();this.searchIndex=this.buildIndex(rawSearchIndex)}buildTypeMapIndex(name,isAssocType){if(name===""||name===null){return null}if(this.typeNameIdMap.has(name)){const obj=this.typeNameIdMap.get(name);obj.assocOnly=isAssocType&&obj.assocOnly;return obj.id}else{const id=this.typeNameIdMap.size;this.typeNameIdMap.set(name,{id,assocOnly:isAssocType});return id}}buildItemSearchTypeAll(types,lowercasePaths){return types.length>0?types.map(type=>this.buildItemSearchType(type,lowercasePaths)):this.EMPTY_GENERICS_ARRAY}buildItemSearchType(type,lowercasePaths,isAssocType){const PATH_INDEX_DATA=0;const GENERICS_DATA=1;const BINDINGS_DATA=2;let pathIndex,generics,bindings;if(typeof type==="number"){pathIndex=type;generics=this.EMPTY_GENERICS_ARRAY;bindings=this.EMPTY_BINDINGS_MAP}else{pathIndex=type[PATH_INDEX_DATA];generics=this.buildItemSearchTypeAll(type[GENERICS_DATA],lowercasePaths,);if(type.length>BINDINGS_DATA&&type[BINDINGS_DATA].length>0){bindings=new Map(type[BINDINGS_DATA].map(binding=>{const[assocType,constraints]=binding;return[this.buildItemSearchType(assocType,lowercasePaths,true).id,this.buildItemSearchTypeAll(constraints,lowercasePaths),]}))}else{bindings=this.EMPTY_BINDINGS_MAP}}let result;if(pathIndex<0){result={id:pathIndex,ty:TY_GENERIC,path:null,exactPath:null,generics,bindings,}}else if(pathIndex===0){result={id:null,ty:null,path:null,exactPath:null,generics,bindings,}}else{const item=lowercasePaths[pathIndex-1];result={id:this.buildTypeMapIndex(item.name,isAssocType),ty:item.ty,path:item.path,exactPath:item.exactPath,generics,bindings,}}const cr=this.TYPES_POOL.get(result.id);if(cr){if(cr.generics.length===result.generics.length&&cr.generics!==result.generics&&cr.generics.every((x,i)=>result.generics[i]===x)){result.generics=cr.generics}if(cr.bindings.size===result.bindings.size&&cr.bindings!==result.bindings){let ok=true;for(const[k,v]of cr.bindings.entries()){const v2=result.bindings.get(v);if(!v2){ok=false;break}if(v!==v2&&v.length===v2.length&&v.every((x,i)=>v2[i]===x)){result.bindings.set(k,v)}else if(v!==v2){ok=false;break}}if(ok){result.bindings=cr.bindings}}if(cr.ty===result.ty&&cr.path===result.path&&cr.bindings===result.bindings&&cr.generics===result.generics&&cr.ty===result.ty){return cr}}this.TYPES_POOL.set(result.id,result);return result}buildFunctionTypeFingerprint(type,output,fps){let input=type.id;if(input===this.typeNameIdOfArray||input===this.typeNameIdOfSlice){input=this.typeNameIdOfArrayOrSlice}if(input===this.typeNameIdOfTuple||input===this.typeNameIdOfUnit){input=this.typeNameIdOfTupleOrUnit}if(input===this.typeNameIdOfFn||input===this.typeNameIdOfFnMut||input===this.typeNameIdOfFnOnce){input=this.typeNameIdOfHof}const hashint1=k=>{k=(~~k+0x7ed55d16)+(k<<12);k=(k ^ 0xc761c23c)^(k>>>19);k=(~~k+0x165667b1)+(k<<5);k=(~~k+0xd3a2646c)^(k<<9);k=(~~k+0xfd7046c5)+(k<<3);return(k ^ 0xb55a4f09)^(k>>>16)};const hashint2=k=>{k=~k+(k<<15);k ^=k>>>12;k+=k<<2;k ^=k>>>4;k=Math.imul(k,2057);return k ^(k>>16)};if(input!==null){const h0a=hashint1(input);const h0b=hashint2(input);const h1a=~~(h0a+Math.imul(h0b,2));const h1b=~~(h0a+Math.imul(h0b,3));const h2a=~~(h0a+Math.imul(h0b,4));const h2b=~~(h0a+Math.imul(h0b,5));output[0]|=(1<<(h0a%32))|(1<<(h1b%32));output[1]|=(1<<(h1a%32))|(1<<(h2b%32));output[2]|=(1<<(h2a%32))|(1<<(h0b%32));fps.add(input)}for(const g of type.generics){this.buildFunctionTypeFingerprint(g,output,fps)}const fb={id:null,ty:0,generics:this.EMPTY_GENERICS_ARRAY,bindings:this.EMPTY_BINDINGS_MAP,};for(const[k,v]of type.bindings.entries()){fb.id=k;fb.generics=v;this.buildFunctionTypeFingerprint(fb,output,fps)}output[3]=fps.size}buildIndex(rawSearchIndex){const buildFunctionSearchTypeCallback=lowercasePaths=>{return functionSearchType=>{if(functionSearchType===0){return null}const INPUTS_DATA=0;const OUTPUT_DATA=1;let inputs,output;if(typeof functionSearchType[INPUTS_DATA]==="number"){inputs=[this.buildItemSearchType(functionSearchType[INPUTS_DATA],lowercasePaths),]}else{inputs=this.buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],lowercasePaths,)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){output=[this.buildItemSearchType(functionSearchType[OUTPUT_DATA],lowercasePaths,),]}else{output=this.buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],lowercasePaths,)}}else{output=[]}const where_clause=[];const l=functionSearchType.length;for(let i=2;inoop);let descShard={crate,shard:0,start:0,len:itemDescShardDecoder.next(),promise:null,resolve:null,};const descShardList=[descShard];this.searchIndexDeprecated.set(crate,new RoaringBitmap(crateCorpus.c));this.searchIndexEmptyDesc.set(crate,new RoaringBitmap(crateCorpus.e));let descIndex=0;const crateRow={crate,ty:3,name:crate,path:"",descShard,descIndex,exactPath:"",desc:crateCorpus.doc,parent:undefined,type:null,id,word:crate,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),bitIndex:0,implDisambiguator:null,};id+=1;searchIndex.push(crateRow);currentIndex+=1;if(!this.searchIndexEmptyDesc.get(crate).contains(0)){descIndex+=1}const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=new Map(crateCorpus.q);const itemReexports=new Map(crateCorpus.r);const itemParentIdxDecoder=new VlqHexDecoder(crateCorpus.i,noop=>noop);const implDisambiguator=new Map(crateCorpus.b);const paths=crateCorpus.p;const aliases=crateCorpus.a;const lowercasePaths=[];const itemFunctionDecoder=new VlqHexDecoder(crateCorpus.f,buildFunctionSearchTypeCallback(lowercasePaths),);let len=paths.length;let lastPath=itemPaths.get(0);for(let i=0;i2){path=itemPaths.has(elem[2])?itemPaths.get(elem[2]):lastPath;lastPath=path}const exactPath=elem.length>3?itemPaths.get(elem[3]):path;lowercasePaths.push({ty,name:name.toLowerCase(),path,exactPath});paths[i]={ty,name,path,exactPath}}lastPath="";len=itemTypes.length;let lastName="";let lastWord="";for(let i=0;i=descShard.len&&!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descShard={crate,shard:descShard.shard+1,start:descShard.start+descShard.len,len:itemDescShardDecoder.next(),promise:null,resolve:null,};descIndex=0;descShardList.push(descShard)}const name=itemNames[i]===""?lastName:itemNames[i];const word=itemNames[i]===""?lastWord:itemNames[i].toLowerCase();const path=itemPaths.has(i)?itemPaths.get(i):lastPath;const type=itemFunctionDecoder.next();if(type!==null){if(type){const fp=this.functionTypeFingerprint.subarray(id*4,(id+1)*4);const fps=new Set();for(const t of type.inputs){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const t of type.output){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const w of type.where_clause){for(const t of w){this.buildFunctionTypeFingerprint(t,fp,fps)}}}}const itemParentIdx=itemParentIdxDecoder.next();const row={crate,ty:itemTypes.charCodeAt(i)-65,name,path,descShard,descIndex,exactPath:itemReexports.has(i)?itemPaths.get(itemReexports.get(i)):path,parent:itemParentIdx>0?paths[itemParentIdx-1]:undefined,type,id,word,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),bitIndex,implDisambiguator:implDisambiguator.has(i)?implDisambiguator.get(i):null,};id+=1;searchIndex.push(row);lastPath=row.path;if(!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descIndex+=1}lastName=name;lastWord=word}if(aliases){const currentCrateAliases=new Map();this.ALIASES.set(crate,currentCrateAliases);for(const alias_name in aliases){if(!Object.prototype.hasOwnProperty.call(aliases,alias_name)){continue}let currentNameAliases;if(currentCrateAliases.has(alias_name)){currentNameAliases=currentCrateAliases.get(alias_name)}else{currentNameAliases=[];currentCrateAliases.set(alias_name,currentNameAliases)}for(const local_alias of aliases[alias_name]){currentNameAliases.push(local_alias+currentIndex)}}}currentIndex+=itemTypes.length;this.searchState.descShards.set(crate,descShardList)}this.TYPES_POOL=new Map();return searchIndex}static parseQuery(userQuery){function itemTypeFromName(typename){const index=itemTypes.findIndex(i=>i===typename);if(index<0){throw["Unknown type filter ",typename]}return index}function convertTypeFilterOnElem(elem){if(elem.typeFilter!==null){let typeFilter=elem.typeFilter;if(typeFilter==="const"){typeFilter="constant"}elem.typeFilter=itemTypeFromName(typeFilter)}else{elem.typeFilter=NO_TYPE_FILTER}for(const elem2 of elem.generics){convertTypeFilterOnElem(elem2)}for(const constraints of elem.bindings.values()){for(const constraint of constraints){convertTypeFilterOnElem(constraint)}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),elems:[],returned:[],foundElems:0,totalElems:0,literalSearch:false,hasReturnArrow:false,error:null,correction:null,proposeCorrectionFrom:null,proposeCorrectionTo:null,typeFingerprint:new Uint32Array(4),}}function parseInput(query,parserState){let foundStopChar=true;while(parserState.pos"){if(isReturnArrow(parserState)){query.hasReturnArrow=true;break}throw["Unexpected ",c," (did you mean ","->","?)"]}else if(parserState.pos>0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]]}throw["Unexpected ",c]}else if(c===" "){skipWhitespace(parserState);continue}if(!foundStopChar){let extra="";if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(parserState.typeFilter!==null){throw["Expected ",","," or ","->",...extra,", found ",c,]}throw["Expected ",",",", ",":"," or ","->",...extra,", found ",c,]}const before=query.elems.length;getFilteredNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}while(parserState.pos1}query.foundElems=query.elems.length+query.returned.length;query.totalElems=parserState.totalElems;return query}async execQuery(parsedQuery,filterCrates,currentCrate){const results_others=new Map(),results_in_args=new Map(),results_returned=new Map();function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}const buildHrefAndPath=item=>{let displayPath;let href;const type=itemTypes[item.ty];const name=item.name;let path=item.path;let exactPath=item.exactPath;if(type==="mod"){displayPath=path+"::";href=this.rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="import"){displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/index.html#reexport."+name}else if(type==="primitive"||type==="keyword"){displayPath="";href=this.rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=this.rootPath+name+"/index.html"}else if(item.parent!==undefined){const myparent=item.parent;let anchor=type+"."+name;const parentType=itemTypes[myparent.ty];let pageType=parentType;let pageName=myparent.name;exactPath=`${myparent.exactPath}::${myparent.name}`;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){const enumNameIdx=item.path.lastIndexOf("::");const enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}if(item.implDisambiguator!==null){anchor=item.implDisambiguator+"/"+anchor}href=this.rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html#"+anchor}else{displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href,`${exactPath}::${name}`]};function pathSplitter(path){const tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}const transformResults=results=>{const duplicates=new Set();const out=[];for(const result of results){if(result.id!==-1){const obj=this.searchIndex[result.id];obj.dist=result.dist;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=res[2]+"|"+obj.ty;if(duplicates.has(obj.fullPath)){continue}if(obj.ty===TY_IMPORT&&duplicates.has(res[2])){continue}if(duplicates.has(res[2]+"|"+TY_IMPORT)){continue}duplicates.add(obj.fullPath);duplicates.add(res[2]);obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out};const sortResults=async(results,isType,preferredCrate)=>{const userQuery=parsedQuery.userQuery;const casedUserQuery=parsedQuery.original;const result_list=[];for(const result of results.values()){result.item=this.searchIndex[result.id];result.word=this.searchIndex[result.id].word;result_list.push(result)}result_list.sort((aaa,bbb)=>{let a,b;a=(aaa.item.name!==casedUserQuery);b=(bbb.item.name!==casedUserQuery);if(a!==b){return a-b}a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.path_dist;b=bbb.path_dist;if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}a=(aaa.dist);b=(bbb.dist);if(a!==b){return a-b}a=this.searchIndexDeprecated.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexDeprecated.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}a=this.searchIndexEmptyDesc.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexEmptyDesc.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});return transformResults(result_list)};function unifyFunctionTypes(fnTypesIn,queryElems,whereClause,mgensIn,solutionCb,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}const mgens=mgensIn===null?null:new Map(mgensIn);if(queryElems.length===0){return!solutionCb||solutionCb(mgens)}if(!fnTypesIn||fnTypesIn.length===0){return false}const ql=queryElems.length;const fl=fnTypesIn.length;if(ql===1&&queryElems[0].generics.length===0&&queryElems[0].bindings.size===0){const queryElem=queryElems[0];for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}if(fnType.id<0&&queryElem.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==queryElem.id){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,queryElem.id);if(!solutionCb||solutionCb(mgensScratch)){return true}}else if(!solutionCb||solutionCb(mgens?new Map(mgens):null)){return true}}for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}if(fnType.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,0);if(unifyFunctionTypes(whereClause[(-fnType.id)-1],queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,)){return true}}else if(unifyFunctionTypes([...fnType.generics,...Array.from(fnType.bindings.values()).flat()],queryElems,whereClause,mgens?new Map(mgens):null,solutionCb,unboxingDepth+1,)){return true}}return false}const fnTypes=fnTypesIn.slice();const flast=fl-1;const qlast=ql-1;const queryElem=queryElems[qlast];let queryElemsTmp=null;for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==queryElem.id){continue}mgensScratch.set(fnType.id,queryElem.id)}else{mgensScratch=mgens}fnTypes[i]=fnTypes[flast];fnTypes.length=flast;if(!queryElemsTmp){queryElemsTmp=queryElems.slice(0,qlast)}const passesUnification=unifyFunctionTypes(fnTypes,queryElemsTmp,whereClause,mgensScratch,mgensScratch=>{if(fnType.generics.length===0&&queryElem.generics.length===0&&fnType.bindings.size===0&&queryElem.bindings.size===0){return!solutionCb||solutionCb(mgensScratch)}const solution=unifyFunctionTypeCheckBindings(fnType,queryElem,whereClause,mgensScratch,unboxingDepth,);if(!solution){return false}const simplifiedGenerics=solution.simplifiedGenerics;for(const simplifiedMgens of solution.mgens){const passesUnification=unifyFunctionTypes(simplifiedGenerics,queryElem.generics,whereClause,simplifiedMgens,solutionCb,unboxingDepth,);if(passesUnification){return true}}return false},unboxingDepth,);if(passesUnification){return true}fnTypes[flast]=fnTypes[i];fnTypes[i]=fnType;fnTypes.length=fl}for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==0){continue}mgensScratch.set(fnType.id,0)}else{mgensScratch=mgens}const generics=fnType.id<0?whereClause[(-fnType.id)-1]:fnType.generics;const bindings=fnType.bindings?Array.from(fnType.bindings.values()).flat():[];const passesUnification=unifyFunctionTypes(fnTypes.toSpliced(i,1,...generics,...bindings),queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,);if(passesUnification){return true}}return false}const unifyFunctionTypeIsMatchCandidate=(fnType,queryElem,mgensIn)=>{if(!typePassesFilter(queryElem.typeFilter,fnType.ty)){return false}if(fnType.id<0&&queryElem.id<0){if(mgensIn){if(mgensIn.has(fnType.id)&&mgensIn.get(fnType.id)!==queryElem.id){return false}for(const[fid,qid]of mgensIn.entries()){if(fnType.id!==fid&&queryElem.id===qid){return false}if(fnType.id===fid&&queryElem.id!==qid){return false}}}return true}else{if(queryElem.id===this.typeNameIdOfArrayOrSlice&&(fnType.id===this.typeNameIdOfSlice||fnType.id===this.typeNameIdOfArray)){}else if(queryElem.id===this.typeNameIdOfTupleOrUnit&&(fnType.id===this.typeNameIdOfTuple||fnType.id===this.typeNameIdOfUnit)){}else if(queryElem.id===this.typeNameIdOfHof&&(fnType.id===this.typeNameIdOfFn||fnType.id===this.typeNameIdOfFnMut||fnType.id===this.typeNameIdOfFnOnce)){}else if(fnType.id!==queryElem.id||queryElem.id===null){return false}if((fnType.generics.length+fnType.bindings.size)===0&&queryElem.generics.length!==0){return false}if(fnType.bindings.size0){const fnTypePath=fnType.path!==undefined&&fnType.path!==null?fnType.path.split("::"):[];if(queryElemPathLength>fnTypePath.length){return false}let i=0;for(const path of fnTypePath){if(path===queryElem.pathWithoutLast[i]){i+=1;if(i>=queryElemPathLength){break}}}if(i0){let mgensSolutionSet=[mgensIn];for(const[name,constraints]of queryElem.bindings.entries()){if(mgensSolutionSet.length===0){return false}if(!fnType.bindings.has(name)){return false}const fnTypeBindings=fnType.bindings.get(name);mgensSolutionSet=mgensSolutionSet.flatMap(mgens=>{const newSolutions=[];unifyFunctionTypes(fnTypeBindings,constraints,whereClause,mgens,newMgens=>{newSolutions.push(newMgens);return false},unboxingDepth,);return newSolutions})}if(mgensSolutionSet.length===0){return false}const binds=Array.from(fnType.bindings.entries()).flatMap(entry=>{const[name,constraints]=entry;if(queryElem.bindings.has(name)){return[]}else{return constraints}});if(simplifiedGenerics.length>0){simplifiedGenerics=[...simplifiedGenerics,...binds]}else{simplifiedGenerics=binds}return{simplifiedGenerics,mgens:mgensSolutionSet}}return{simplifiedGenerics,mgens:[mgensIn]}}function unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}if(fnType.id<0&&queryElem.id>=0){if(!whereClause){return false}if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){return false}const mgensTmp=new Map(mgens);mgensTmp.set(fnType.id,null);return checkIfInList(whereClause[(-fnType.id)-1],queryElem,whereClause,mgensTmp,unboxingDepth,)}else if(fnType.generics.length>0||fnType.bindings.size>0){const simplifiedGenerics=[...fnType.generics,...Array.from(fnType.bindings.values()).flat(),];return checkIfInList(simplifiedGenerics,queryElem,whereClause,mgens,unboxingDepth,)}return false}function checkIfInList(list,elem,whereClause,mgens,unboxingDepth){for(const entry of list){if(checkType(entry,elem,whereClause,mgens,unboxingDepth)){return true}}return false}const checkType=(row,elem,whereClause,mgens,unboxingDepth)=>{if(unboxingDepth>=UNBOXING_LIMIT){return false}if(row.bindings.size===0&&elem.bindings.size===0){if(elem.id<0&&mgens===null){return row.id<0||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth+1,)}if(row.id>0&&elem.id>0&&elem.pathWithoutLast.length===0&&typePassesFilter(elem.typeFilter,row.ty)&&elem.generics.length===0&&elem.id!==this.typeNameIdOfArrayOrSlice&&elem.id!==this.typeNameIdOfTupleOrUnit&&elem.id!==this.typeNameIdOfHof){return row.id===elem.id||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth,)}}return unifyFunctionTypes([row],[elem],whereClause,mgens,null,unboxingDepth)};function checkPath(contains,ty){if(contains.length===0){return 0}const maxPathEditDistance=Math.floor(contains.reduce((acc,next)=>acc+next.length,0)/3,);let ret_dist=maxPathEditDistance+1;const path=ty.path.split("::");if(ty.parent&&ty.parent.name){path.push(ty.parent.name.toLowerCase())}const length=path.length;const clength=contains.length;pathiter:for(let i=length-clength;i>=0;i-=1){let dist_total=0;for(let x=0;xmaxPathEditDistance){continue pathiter}dist_total+=dist}}ret_dist=Math.min(ret_dist,Math.round(dist_total/clength))}return ret_dist>maxPathEditDistance?null:ret_dist}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,descShard:item.descShard,descIndex:item.descIndex,exactPath:item.exactPath,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,bitIndex:item.bitIndex,implDisambiguator:item.implDisambiguator,}}const handleAliases=async(ret,query,filterCrates,currentCrate)=>{const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(this.ALIASES.has(filterCrates)&&this.ALIASES.get(filterCrates).has(lowerQuery)){const query_aliases=this.ALIASES.get(filterCrates).get(lowerQuery);for(const alias of query_aliases){aliases.push(createAliasFromItem(this.searchIndex[alias]))}}}else{for(const[crate,crateAliasesIndex]of this.ALIASES){if(crateAliasesIndex.has(lowerQuery)){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=crateAliasesIndex.get(lowerQuery);for(const alias of query_aliases){pushTo.push(createAliasFromItem(this.searchIndex[alias]))}}}}const sortFunc=(aaa,bbb)=>{if(aaa.path{return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex)?"":this.searchState.loadDesc(alias)};const[crateDescs,descs]=await Promise.all([Promise.all(crateAliases.map(fetchDesc)),Promise.all(aliases.map(fetchDesc)),]);const pushFunc=alias=>{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach((alias,i)=>{alias.desc=descs[i]});aliases.forEach(pushFunc);crateAliases.forEach((alias,i)=>{alias.desc=crateDescs[i]});crateAliases.forEach(pushFunc)};function addIntoResults(results,fullId,id,index,dist,path_dist,maxEditDistance){if(dist<=maxEditDistance||index!==-1){if(results.has(fullId)){const result=results.get(fullId);if(result.dontValidate||result.dist<=dist){return}}results.set(fullId,{id:id,index:index,dontValidate:parsedQuery.literalSearch,dist:dist,path_dist:path_dist,})}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned,maxEditDistance,){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let path_dist=0;const fullId=row.id;const tfpDist=compareTypeFingerprints(fullId,parsedQuery.typeFingerprint,);if(tfpDist!==null){const in_args=row.type&&row.type.inputs&&checkIfInList(row.type.inputs,elem,row.type.where_clause,null,0);const returned=row.type&&row.type.output&&checkIfInList(row.type.output,elem,row.type.where_clause,null,0);if(in_args){results_in_args.max_dist=Math.max(results_in_args.max_dist||0,tfpDist);const maxDist=results_in_args.sizenormalizedIndex&&normalizedIndex!==-1)){index=normalizedIndex}if(elem.fullPath.length>1){path_dist=checkPath(elem.pathWithoutLast,row);if(path_dist===null){return}}if(parsedQuery.literalSearch){if(row.word===elem.pathLast){addIntoResults(results_others,fullId,pos,index,0,path_dist)}return}const dist=editDistance(row.normalizedName,elem.normalizedPathLast,maxEditDistance);if(index===-1&&dist>maxEditDistance){return}addIntoResults(results_others,fullId,pos,index,dist,path_dist,maxEditDistance)}function handleArgs(row,pos,results){if(!row||(filterCrates!==null&&row.crate!==filterCrates)||!row.type){return}const tfpDist=compareTypeFingerprints(row.id,parsedQuery.typeFingerprint,);if(tfpDist===null){return}if(results.size>=MAX_RESULTS&&tfpDist>results.max_dist){return}if(!unifyFunctionTypes(row.type.inputs,parsedQuery.elems,row.type.where_clause,null,mgens=>{return unifyFunctionTypes(row.type.output,parsedQuery.returned,row.type.where_clause,mgens,null,0,)},0,)){return}results.max_dist=Math.max(results.max_dist||0,tfpDist);addIntoResults(results,row.id,pos,0,tfpDist,0,Number.MAX_VALUE)}const compareTypeFingerprints=(fullId,queryFingerprint)=>{const fh0=this.functionTypeFingerprint[fullId*4];const fh1=this.functionTypeFingerprint[(fullId*4)+1];const fh2=this.functionTypeFingerprint[(fullId*4)+2];const[qh0,qh1,qh2]=queryFingerprint;const[in0,in1,in2]=[fh0&qh0,fh1&qh1,fh2&qh2];if((in0 ^ qh0)||(in1 ^ qh1)||(in2 ^ qh2)){return null}return this.functionTypeFingerprint[(fullId*4)+3]};const innerRunQuery=()=>{const queryLen=parsedQuery.elems.reduce((acc,next)=>acc+next.pathLast.length,0)+parsedQuery.returned.reduce((acc,next)=>acc+next.pathLast.length,0);const maxEditDistance=Math.floor(queryLen/3);const genericSymbols=new Map();const convertNameToId=(elem,isAssocType)=>{const loweredName=elem.pathLast.toLowerCase();if(this.typeNameIdMap.has(loweredName)&&(isAssocType||!this.typeNameIdMap.get(loweredName).assocOnly)){elem.id=this.typeNameIdMap.get(loweredName).id}else if(!parsedQuery.literalSearch){let match=null;let matchDist=maxEditDistance+1;let matchName="";for(const[name,{id,assocOnly}]of this.typeNameIdMap){const dist=Math.min(editDistance(name,loweredName,maxEditDistance),editDistance(name,elem.normalizedPathLast,maxEditDistance),);if(dist<=matchDist&&dist<=maxEditDistance&&(isAssocType||!assocOnly)){if(dist===matchDist&&matchName>name){continue}match=id;matchDist=dist;matchName=name}}if(match!==null){parsedQuery.correction=matchName}elem.id=match}if((elem.id===null&&parsedQuery.totalElems>1&&elem.typeFilter===-1&&elem.generics.length===0&&elem.bindings.size===0)||elem.typeFilter===TY_GENERIC){if(genericSymbols.has(elem.name)){elem.id=genericSymbols.get(elem.name)}else{elem.id=-(genericSymbols.size+1);genericSymbols.set(elem.name,elem.id)}if(elem.typeFilter===-1&&elem.name.length>=3){const maxPartDistance=Math.floor(elem.name.length/3);let matchDist=maxPartDistance+1;let matchName="";for(const name of this.typeNameIdMap.keys()){const dist=editDistance(name,elem.name,maxPartDistance);if(dist<=matchDist&&dist<=maxPartDistance){if(dist===matchDist&&matchName>name){continue}matchDist=dist;matchName=name}}if(matchName!==""){parsedQuery.proposeCorrectionFrom=elem.name;parsedQuery.proposeCorrectionTo=matchName}}elem.typeFilter=TY_GENERIC}if(elem.generics.length>0&&elem.typeFilter===TY_GENERIC){parsedQuery.error=["Generic type parameter ",elem.name," does not accept generic parameters",]}for(const elem2 of elem.generics){convertNameToId(elem2)}elem.bindings=new Map(Array.from(elem.bindings.entries()).map(entry=>{const[name,constraints]=entry;if(!this.typeNameIdMap.has(name)){parsedQuery.error=["Type parameter ",name," does not exist",];return[null,[]]}for(const elem2 of constraints){convertNameToId(elem2)}return[this.typeNameIdMap.get(name).id,constraints]}),)};const fps=new Set();for(const elem of parsedQuery.elems){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}for(const elem of parsedQuery.returned){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}if(parsedQuery.foundElems===1&&!parsedQuery.hasReturnArrow){if(parsedQuery.elems.length===1){const elem=parsedQuery.elems[0];const length=this.searchIndex.length;for(let i=0,nSearchIndex=length;i0){const sortQ=(a,b)=>{const ag=a.generics.length===0&&a.bindings.size===0;const bg=b.generics.length===0&&b.bindings.size===0;if(ag!==bg){return ag-bg}const ai=a.id>0;const bi=b.id>0;return ai-bi};parsedQuery.elems.sort(sortQ);parsedQuery.returned.sort(sortQ);for(let i=0,nSearchIndex=this.searchIndex.length;i{const descs=await Promise.all(list.map(result=>{return this.searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex)?"":this.searchState.loadDesc(result)}));for(const[i,result]of list.entries()){result.desc=descs[i]}}));if(parsedQuery.error!==null&&ret.others.length!==0){ret.query.error=null}return ret}}let rawSearchIndex;let docSearch;const longItemTypes=["keyword","primitive type","module","extern crate","re-export","struct","enum","function","type alias","static","trait","","trait method","method","struct field","enum variant","macro","assoc type","constant","assoc const","union","foreign type","existential type","attribute macro","derive macro","trait alias",];let currentResults;function printTab(nb){let iter=0;let foundCurrentTab=false;let foundCurrentResultSet=false;onEachLazy(document.getElementById("search-tabs").childNodes,elem=>{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});const isTypeSearch=(nb>0||iter===1);iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb;const correctionsElem=document.getElementsByClassName("search-corrections");if(isTypeSearch){removeClass(correctionsElem[0],"hidden")}else{addClass(correctionsElem[0],"hidden")}}else if(nb!==0){printTab(0)}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="all crates"&&window.searchIndex.has(elem.value)){return elem.value}return null}function nextTab(direction){const next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){const target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#search-tabs button").item(searchState.currentTab);searchState.focusedByTab[searchState.currentTab]=null;if(target){target.focus()}}async function addTab(array,query,display){const extraClass=display?" active":"";const output=document.createElement("div");if(array.length>0){output.className="search-results "+extraClass;for(const item of array){const name=item.name;const type=itemTypes[item.ty];const longType=longItemTypes[item.ty];const typeName=longType.length!==0?`${longType}`:"?";const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const resultName=document.createElement("div");resultName.className="result-name";resultName.insertAdjacentHTML("beforeend",`${typeName}`);link.appendChild(resultName);let alias=" ";if(item.is_alias){alias=`
\ +${item.alias} - see \ +
`}resultName.insertAdjacentHTML("beforeend",`
${alias}\ +${item.displayPath}${name}\ +
`);const description=document.createElement("div");description.className="desc";description.insertAdjacentHTML("beforeend",item.desc);link.appendChild(description);output.appendChild(link)}}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,array.length]}function makeTabHeader(tabNb,text,nbElems){const fmtNbElems=nbElems<10?`\u{2007}(${nbElems})\u{2007}\u{2007}`:nbElems<100?`\u{2007}(${nbElems})\u{2007}`:`\u{2007}(${nbElems})`;if(searchState.currentTab===tabNb){return""}return""}async function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true")){window.onunload=()=>{};searchState.removeQueryParameters();const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=DocSearch.parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const[ret_others,ret_in_args,ret_returned]=await Promise.all([addTab(results.others,results.query,true),addTab(results.in_args,results.query,false),addTab(results.returned,results.query,false),]);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";if(rawSearchIndex.size>1){crates="
in 
"+"
"}let output=`
\ +

Results

${crates}
`;if(results.query.error!==null){const error=results.query.error;error.forEach((value,index)=>{value=value.split("<").join("<").split(">").join(">");if(index%2!==0){error[index]=`${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`

Query parser error: "${error.join("")}".

`;output+="
"+makeTabHeader(0,"In Names",ret_others[1])+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
"+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
";currentTab=0}if(results.query.correction!==null){const orig=results.query.returned.length>0?results.query.returned[0].name:results.query.elems[0].name;output+="

"+`Type "${orig}" not found. `+"Showing results for closest type name "+`"${results.query.correction}" instead.

`}if(results.query.proposeCorrectionFrom!==null){const orig=results.query.proposeCorrectionFrom;const targ=results.query.proposeCorrectionTo;output+="

"+`Type "${orig}" not found and used as generic parameter. `+`Consider searching for "${targ}" instead.

`}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;if(searchState.rustdocToolbar){search.querySelector(".main-heading").appendChild(searchState.rustdocToolbar)}const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("search-tabs").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function updateSearchHistory(url){if(!browserSupportsHistoryApi()){return}const params=searchState.getQueryStringParams();if(!history.state&&!params.search){history.pushState(null,"",url)}else{history.replaceState(null,"",url)}}async function search(forced){const query=DocSearch.parseQuery(searchState.input.value.trim());let filterCrates=getFilterCrates();if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}searchState.setLoadingSearch();const params=searchState.getQueryStringParams();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="\""+query.original+"\" Search - Rust";updateSearchHistory(buildUrl(query.original,filterCrates));await showResults(await docSearch.execQuery(query,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;e.preventDefault();search()}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="all crates"){const query=searchState.input.value.trim();updateSearchHistory(buildUrl(query,null))}currentResults=null;search(true)}function initSearch(searchIndx){rawSearchIndex=searchIndx;if(typeof window!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}else if(typeof exports!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);exports.docSearch=docSearch;exports.parseQuery=DocSearch.parseQuery}}if(typeof exports!=="undefined"){exports.initSearch=initSearch}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch(new Map())}})() \ No newline at end of file diff --git a/static.files/settings-805db61a62df4bd2.js b/static.files/settings-805db61a62df4bd2.js new file mode 100644 index 00000000..4a30479d --- /dev/null +++ b/static.files/settings-805db61a62df4bd2.js @@ -0,0 +1,17 @@ +"use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){if(settingName==="theme"){const useSystem=value==="system preference"?"true":"false";updateLocalStorage("use-system-theme",useSystem)}updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":updateTheme();updateLightAndDark();break;case"line-numbers":if(value===true){window.rustdoc_add_line_numbers_to_examples()}else{window.rustdoc_remove_line_numbers_from_examples()}break;case"hide-sidebar":if(value===true){addClass(document.documentElement,"hide-sidebar")}else{removeClass(document.documentElement,"hide-sidebar")}break;case"hide-toc":if(value===true){addClass(document.documentElement,"hide-toc")}else{removeClass(document.documentElement,"hide-toc")}break;case"hide-modnav":if(value===true){addClass(document.documentElement,"hide-modnav")}else{removeClass(document.documentElement,"hide-modnav")}break}}function showLightAndDark(){removeClass(document.getElementById("preferred-light-theme"),"hidden");removeClass(document.getElementById("preferred-dark-theme"),"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme"),"hidden");addClass(document.getElementById("preferred-dark-theme"),"hidden")}function updateLightAndDark(){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||(useSystem===null&&getSettingValue("theme")===null)){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"),toggle=>{const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=()=>{changeSetting(toggle.id,toggle.checked)}});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;let settingValue=getSettingValue(settingId);if(settingId==="theme"){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||settingValue===null){settingValue=useSystem==="false"?"light":"system preference"}}if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){if(setting==="hr"){output+="
";continue}const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`\ +
+
${setting_name}
+
`;onEach(setting["options"],option=>{const checked=option===setting["default"]?" checked":"";const full=`${js_data_name}-${option.replace(/ /g,"-")}`;output+=`\ + `});output+=`\ +
+
`}else{const checked=setting["default"]===true?" checked":"";output+=`\ +
\ + \ +
`}}return output}function buildSettingsPage(){const theme_names=getVar("themes").split(",").filter(t=>t);theme_names.push("light","dark","ayu");const settings=[{"name":"Theme","js_name":"theme","default":"system preference","options":theme_names.concat("system preference"),},{"name":"Preferred light theme","js_name":"preferred-light-theme","default":"light","options":theme_names,},{"name":"Preferred dark theme","js_name":"preferred-dark-theme","default":"dark","options":theme_names,},{"name":"Auto-hide item contents for large items","js_name":"auto-hide-large-items","default":true,},{"name":"Auto-hide item methods' documentation","js_name":"auto-hide-method-docs","default":false,},{"name":"Auto-hide trait implementation documentation","js_name":"auto-hide-trait-implementations","default":false,},{"name":"Directly go to item in search if there is only one result","js_name":"go-to-only-result","default":false,},{"name":"Show line numbers on code examples","js_name":"line-numbers","default":false,},{"name":"Hide persistent navigation bar","js_name":"hide-sidebar","default":false,},{"name":"Hide table of contents","js_name":"hide-toc","default":false,},{"name":"Hide module navigation","js_name":"hide-modnav","default":false,},{"name":"Disable keyboard shortcuts","js_name":"disable-shortcuts","default":false,},];const elementKind=isSettingsPage?"section":"div";const innerHTML=`
${buildSettingsPageSections(settings)}
`;const el=document.createElement(elementKind);el.id="settings";if(!isSettingsPage){el.className="popover"}el.innerHTML=innerHTML;if(isSettingsPage){document.getElementById(MAIN_ID).appendChild(el)}else{el.setAttribute("tabindex","-1");getSettingsButton().appendChild(el)}return el}const settingsMenu=buildSettingsPage();function displaySettings(){settingsMenu.style.display="";onEachLazy(settingsMenu.querySelectorAll("input[type='checkbox']"),el=>{const val=getSettingValue(el.id);const checked=val==="true";if(checked!==el.checked&&val!==null){el.checked=checked}})}function settingsBlurHandler(event){if(!getHelpButton().contains(document.activeElement)&&!getHelpButton().contains(event.relatedTarget)&&!getSettingsButton().contains(document.activeElement)&&!getSettingsButton().contains(event.relatedTarget)){window.hidePopoverMenus()}}if(!isSettingsPage){const settingsButton=getSettingsButton();const settingsMenu=document.getElementById("settings");settingsButton.onclick=event=>{if(settingsMenu.contains(event.target)){return}event.preventDefault();const shouldDisplaySettings=settingsMenu.style.display==="none";window.hideAllModals();if(shouldDisplaySettings){displaySettings()}};settingsButton.onblur=settingsBlurHandler;settingsButton.querySelector("a").onblur=settingsBlurHandler;onEachLazy(settingsMenu.querySelectorAll("input"),el=>{el.onblur=settingsBlurHandler});settingsMenu.onblur=settingsBlurHandler}setTimeout(()=>{setEvents(settingsMenu);if(!isSettingsPage){displaySettings()}removeClass(getSettingsButton(),"rotate")},0)})() \ No newline at end of file diff --git a/static.files/src-script-e66d777a5a92e9b2.js b/static.files/src-script-e66d777a5a92e9b2.js new file mode 100644 index 00000000..d0aebb85 --- /dev/null +++ b/static.files/src-script-e66d777a5a92e9b2.js @@ -0,0 +1 @@ +"use strict";(function(){const rootPath=getVar("root-path");const NAME_OFFSET=0;const DIRS_OFFSET=1;const FILES_OFFSET=2;const RUSTDOC_MOBILE_BREAKPOINT=700;function closeSidebarIfMobile(){if(window.innerWidth{removeClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","false")};window.rustdocShowSourceSidebar=()=>{addClass(document.documentElement,"src-sidebar-expanded");updateLocalStorage("source-sidebar-show","true")};window.rustdocToggleSrcSidebar=()=>{if(document.documentElement.classList.contains("src-sidebar-expanded")){window.rustdocCloseSourceSidebar()}else{window.rustdocShowSourceSidebar()}};function createSrcSidebar(){const container=document.querySelector("nav.sidebar");const sidebar=document.createElement("div");sidebar.id="src-sidebar";let hasFoundFile=false;for(const[key,source]of srcIndex){source[NAME_OFFSET]=key;hasFoundFile=createDirEntry(source,sidebar,"",hasFoundFile)}container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}function highlightSrcLines(){const match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("a"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSrcHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSrcLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)||ev.ctrlKey||ev.altKey||ev.metaKey){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",highlightSrcLines);onEachLazy(document.getElementsByClassName("src-line-numbers"),el=>{el.addEventListener("click",handleSrcHighlight)});highlightSrcLines();window.createSrcSidebar=createSrcSidebar})() \ No newline at end of file diff --git a/static.files/storage-1d39b6787ed640ff.js b/static.files/storage-1d39b6787ed640ff.js new file mode 100644 index 00000000..5aac776b --- /dev/null +++ b/static.files/storage-1d39b6787ed640ff.js @@ -0,0 +1,23 @@ +"use strict";const builtinThemes=["light","dark","ayu"];const darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");const settingsDataset=(function(){const settingsElement=document.getElementById("default-settings");return settingsElement&&settingsElement.dataset?settingsElement.dataset:null})();function getSettingValue(settingName){const current=getCurrentValue(settingName);if(current===null&&settingsDataset!==null){const def=settingsDataset[settingName.replace(/-/g,"_")];if(def!==undefined){return def}}return current}const localStoredTheme=getSettingValue("theme");function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(elem&&elem.classList){elem.classList.add(className)}}function removeClass(elem,className){if(elem&&elem.classList){elem.classList.remove(className)}}function onEach(arr,func){for(const elem of arr){if(func(elem)){return true}}return false}function onEachLazy(lazyArray,func){return onEach(Array.prototype.slice.call(lazyArray),func)}function updateLocalStorage(name,value){try{window.localStorage.setItem("rustdoc-"+name,value)}catch(e){}}function getCurrentValue(name){try{return window.localStorage.getItem("rustdoc-"+name)}catch(e){return null}}const getVar=(function getVar(name){const el=document.querySelector("head > meta[name='rustdoc-vars']");return el?el.attributes["data-"+name].value:null});function switchTheme(newThemeName,saveTheme){const themeNames=getVar("themes").split(",").filter(t=>t);themeNames.push(...builtinThemes);if(themeNames.indexOf(newThemeName)===-1){return}if(saveTheme){updateLocalStorage("theme",newThemeName)}document.documentElement.setAttribute("data-theme",newThemeName);if(builtinThemes.indexOf(newThemeName)!==-1){if(window.currentTheme){window.currentTheme.parentNode.removeChild(window.currentTheme);window.currentTheme=null}}else{const newHref=getVar("root-path")+encodeURIComponent(newThemeName)+getVar("resource-suffix")+".css";if(!window.currentTheme){if(document.readyState==="loading"){document.write(``);window.currentTheme=document.getElementById("themeStyle")}else{window.currentTheme=document.createElement("link");window.currentTheme.rel="stylesheet";window.currentTheme.id="themeStyle";window.currentTheme.href=newHref;document.documentElement.appendChild(window.currentTheme)}}else if(newHref!==window.currentTheme.href){window.currentTheme.href=newHref}}}const updateTheme=(function(){const mql=window.matchMedia("(prefers-color-scheme: dark)");function updateTheme(){if(getSettingValue("use-system-theme")!=="false"){const lightTheme=getSettingValue("preferred-light-theme")||"light";const darkTheme=getSettingValue("preferred-dark-theme")||"dark";updateLocalStorage("use-system-theme","true");switchTheme(mql.matches?darkTheme:lightTheme,true)}else{switchTheme(getSettingValue("theme"),false)}}mql.addEventListener("change",updateTheme);return updateTheme})();if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("preferred-dark-theme",localStoredTheme)}}updateTheme();if(getSettingValue("source-sidebar-show")==="true"){addClass(document.documentElement,"src-sidebar-expanded")}if(getSettingValue("hide-sidebar")==="true"){addClass(document.documentElement,"hide-sidebar")}if(getSettingValue("hide-toc")==="true"){addClass(document.documentElement,"hide-toc")}if(getSettingValue("hide-modnav")==="true"){addClass(document.documentElement,"hide-modnav")}function updateSidebarWidth(){const desktopSidebarWidth=getSettingValue("desktop-sidebar-width");if(desktopSidebarWidth&&desktopSidebarWidth!=="null"){document.documentElement.style.setProperty("--desktop-sidebar-width",desktopSidebarWidth+"px",)}const srcSidebarWidth=getSettingValue("src-sidebar-width");if(srcSidebarWidth&&srcSidebarWidth!=="null"){document.documentElement.style.setProperty("--src-sidebar-width",srcSidebarWidth+"px",)}}updateSidebarWidth();window.addEventListener("pageshow",ev=>{if(ev.persisted){setTimeout(updateTheme,0);setTimeout(updateSidebarWidth,0)}});class RustdocSearchElement extends HTMLElement{constructor(){super()}connectedCallback(){const rootPath=getVar("root-path");const currentCrate=getVar("current-crate");this.innerHTML=``}}window.customElements.define("rustdoc-search",RustdocSearchElement);class RustdocToolbarElement extends HTMLElement{constructor(){super()}connectedCallback(){if(this.firstElementChild){return}const rootPath=getVar("root-path");this.innerHTML=` +
+ Settings +
+
+ Help +
+ `}}window.customElements.define("rustdoc-toolbar",RustdocToolbarElement) \ No newline at end of file diff --git a/trait.impl/actix_service/ext/trait.ServiceExt.js b/trait.impl/actix_service/ext/trait.ServiceExt.js new file mode 100644 index 00000000..bbaf644c --- /dev/null +++ b/trait.impl/actix_service/ext/trait.ServiceExt.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20]} \ No newline at end of file diff --git a/trait.impl/actix_service/ext/trait.ServiceFactoryExt.js b/trait.impl/actix_service/ext/trait.ServiceFactoryExt.js new file mode 100644 index 00000000..bbaf644c --- /dev/null +++ b/trait.impl/actix_service/ext/trait.ServiceFactoryExt.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20]} \ No newline at end of file diff --git a/trait.impl/actix_service/ext/trait.TransformExt.js b/trait.impl/actix_service/ext/trait.TransformExt.js new file mode 100644 index 00000000..bbaf644c --- /dev/null +++ b/trait.impl/actix_service/ext/trait.TransformExt.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20]} \ No newline at end of file diff --git a/trait.impl/actix_service/trait.IntoService.js b/trait.impl/actix_service/trait.IntoService.js new file mode 100644 index 00000000..bbaf644c --- /dev/null +++ b/trait.impl/actix_service/trait.IntoService.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20]} \ No newline at end of file diff --git a/trait.impl/actix_service/trait.IntoServiceFactory.js b/trait.impl/actix_service/trait.IntoServiceFactory.js new file mode 100644 index 00000000..bbaf644c --- /dev/null +++ b/trait.impl/actix_service/trait.IntoServiceFactory.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20]} \ No newline at end of file diff --git a/trait.impl/actix_service/trait.Service.js b/trait.impl/actix_service/trait.Service.js new file mode 100644 index 00000000..01aea7d8 --- /dev/null +++ b/trait.impl/actix_service/trait.Service.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]],["actix_tls",[["impl<IO: ActixStream + 'static> Service<IO> for AcceptorService"],["impl<IO: ActixStream> Service<IO> for AcceptorService"],["impl<IO: ActixStream> Service<IO> for AcceptorService"],["impl<IO: ActixStream> Service<IO> for AcceptorService"],["impl<IO: ActixStream> Service<IO> for AcceptorService"],["impl<IO: ActixStream> Service<IO> for AcceptorService"],["impl<R, IO> Service<Connection<R, IO>> for TlsConnector
where\n R: Host,\n IO: ActixStream + 'static,
"],["impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where\n R: Host,\n IO: ActixStream,
"],["impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where\n R: Host,\n IO: ActixStream,
"],["impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where\n R: Host,\n IO: ActixStream,
"],["impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where\n R: Host,\n IO: ActixStream,
"],["impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
where\n R: Host,\n IO: ActixStream,
"],["impl<R: Host> Service<ConnectInfo<R>> for ConnectorService"],["impl<R: Host> Service<ConnectInfo<R>> for ResolverService"],["impl<R: Host> Service<ConnectInfo<R>> for TcpConnectorService"]]],["actix_tracing",[["impl<S, Req, F> Service<Req> for TracingService<S, F>
where\n S: Service<Req>,\n F: Fn(&Req) -> Option<Span>,
"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20,5980,691]} \ No newline at end of file diff --git a/trait.impl/actix_service/trait.ServiceFactory.js b/trait.impl/actix_service/trait.ServiceFactory.js new file mode 100644 index 00000000..0054159c --- /dev/null +++ b/trait.impl/actix_service/trait.ServiceFactory.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]],["actix_tls",[["impl<IO: ActixStream + 'static> ServiceFactory<IO> for Acceptor"],["impl<IO: ActixStream> ServiceFactory<IO> for Acceptor"],["impl<IO: ActixStream> ServiceFactory<IO> for Acceptor"],["impl<IO: ActixStream> ServiceFactory<IO> for Acceptor"],["impl<IO: ActixStream> ServiceFactory<IO> for Acceptor"],["impl<IO: ActixStream> ServiceFactory<IO> for Acceptor"],["impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where\n R: Host,\n IO: ActixStream + 'static,
"],["impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where\n R: Host,\n IO: ActixStream + 'static,
"],["impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where\n R: Host,\n IO: ActixStream + 'static,
"],["impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where\n R: Host,\n IO: ActixStream + 'static,
"],["impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where\n R: Host,\n IO: ActixStream + 'static,
"],["impl<R: Host> ServiceFactory<ConnectInfo<R>> for Connector"],["impl<R: Host> ServiceFactory<ConnectInfo<R>> for Resolver"],["impl<R: Host> ServiceFactory<ConnectInfo<R>> for TcpConnector"],["impl<R: Host, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
where\n IO: ActixStream + 'static,
"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20,5833]} \ No newline at end of file diff --git a/trait.impl/actix_service/transform/trait.Transform.js b/trait.impl/actix_service/transform/trait.Transform.js new file mode 100644 index 00000000..eef6101e --- /dev/null +++ b/trait.impl/actix_service/transform/trait.Transform.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_service",[]],["actix_tracing",[["impl<S, Req, U, F> Transform<S, Req> for TracingTransform<S, U, F>
where\n S: Service<Req>,\n U: ServiceFactory<Req, Response = S::Response, Error = S::Error, Service = S>,\n F: Fn(&Req) -> Option<Span> + Clone,
"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[20,935]} \ No newline at end of file diff --git a/trait.impl/actix_tls/connect/host/trait.Host.js b/trait.impl/actix_tls/connect/host/trait.Host.js new file mode 100644 index 00000000..6aa325a1 --- /dev/null +++ b/trait.impl/actix_tls/connect/host/trait.Host.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[16]} \ No newline at end of file diff --git a/trait.impl/core/borrow/trait.Borrow.js b/trait.impl/core/borrow/trait.Borrow.js new file mode 100644 index 00000000..f1cd78f0 --- /dev/null +++ b/trait.impl/core/borrow/trait.Borrow.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["bytestring",[["impl Borrow<str> for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[391]} \ No newline at end of file diff --git a/trait.impl/core/clone/trait.Clone.js b/trait.impl/core/clone/trait.Clone.js new file mode 100644 index 00000000..3d22b999 --- /dev/null +++ b/trait.impl/core/clone/trait.Clone.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Clone for BytesCodec"],["impl Clone for LinesCodec"]]],["actix_rt",[["impl Clone for ArbiterHandle"],["impl Clone for System"]]],["actix_server",[["impl Clone for MpTcp"],["impl Clone for ServerHandle"]]],["actix_service",[["impl<T, S, Req> Clone for ApplyTransform<T, S, Req>"]]],["actix_tls",[["impl Clone for Acceptor"],["impl Clone for Acceptor"],["impl Clone for Acceptor"],["impl Clone for Acceptor"],["impl Clone for Acceptor"],["impl Clone for Acceptor"],["impl Clone for TlsConnector"],["impl Clone for TlsConnector"],["impl Clone for TlsConnectorService"],["impl Clone for TlsConnector"],["impl Clone for TlsConnectorService"],["impl Clone for TlsConnector"],["impl Clone for TlsConnectorService"],["impl Clone for TlsConnector"],["impl Clone for TlsConnectorService"],["impl Clone for TlsConnector"],["impl Clone for TlsConnectorService"],["impl Clone for Connector"],["impl Clone for ConnectorService"],["impl Clone for Resolver"],["impl Clone for ResolverService"],["impl Clone for TcpConnector"],["impl Clone for TcpConnectorService"]]],["actix_tracing",[["impl<S: Clone, F: Clone> Clone for TracingService<S, F>"]]],["actix_utils",[["impl Clone for Counter"],["impl<L: Clone, R: Clone> Clone for Either<L, R>"],["impl<T: Clone> Clone for Ready<T>"]]],["bytestring",[["impl Clone for ByteString"]]],["local_channel",[["impl<T> Clone for Sender<T>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[553,536,544,338,7074,600,1277,283,309]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.Eq.js b/trait.impl/core/cmp/trait.Eq.js new file mode 100644 index 00000000..6bb2dca3 --- /dev/null +++ b/trait.impl/core/cmp/trait.Eq.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl<R: Eq> Eq for ConnectInfo<R>"]]],["bytestring",[["impl Eq for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[427,270]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.Ord.js b/trait.impl/core/cmp/trait.Ord.js new file mode 100644 index 00000000..bf42acf6 --- /dev/null +++ b/trait.impl/core/cmp/trait.Ord.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["bytestring",[["impl Ord for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[272]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.PartialEq.js b/trait.impl/core/cmp/trait.PartialEq.js new file mode 100644 index 00000000..53822bb6 --- /dev/null +++ b/trait.impl/core/cmp/trait.PartialEq.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl<R: PartialEq> PartialEq for ConnectInfo<R>"]]],["bytestring",[["impl PartialEq<str> for ByteString"],["impl<T: AsRef<str>> PartialEq<T> for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[469,931]} \ No newline at end of file diff --git a/trait.impl/core/cmp/trait.PartialOrd.js b/trait.impl/core/cmp/trait.PartialOrd.js new file mode 100644 index 00000000..3ce73da2 --- /dev/null +++ b/trait.impl/core/cmp/trait.PartialOrd.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["bytestring",[["impl PartialOrd for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[293]} \ No newline at end of file diff --git a/trait.impl/core/convert/trait.AsRef.js b/trait.impl/core/convert/trait.AsRef.js new file mode 100644 index 00000000..5860abce --- /dev/null +++ b/trait.impl/core/convert/trait.AsRef.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["bytestring",[["impl AsRef<str> for ByteString"],["impl AsRef<ByteString> for ByteString"],["impl AsRef<[u8]> for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1159]} \ No newline at end of file diff --git a/trait.impl/core/convert/trait.From.js b/trait.impl/core/convert/trait.From.js new file mode 100644 index 00000000..0c9d413e --- /dev/null +++ b/trait.impl/core/convert/trait.From.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_rt",[["impl From<Runtime> for Runtime"]]],["actix_tls",[["impl<IO> From<TlsStream<IO>> for TlsStream<IO>"],["impl<IO> From<SslStream<IO>> for TlsStream<IO>"],["impl<IO> From<TlsStream<IO>> for TlsStream<IO>"],["impl<IO> From<TlsStream<IO>> for TlsStream<IO>"],["impl<IO> From<TlsStream<IO>> for TlsStream<IO>"],["impl<IO> From<TlsStream<IO>> for TlsStream<IO>"],["impl<R: Host> From<R> for ConnectInfo<R>"]]],["bytestring",[["impl From<&str> for ByteString"],["impl From<ByteString> for String"],["impl From<Box<str>> for ByteString"],["impl From<String> for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[283,2867,1743]} \ No newline at end of file diff --git a/trait.impl/core/convert/trait.TryFrom.js b/trait.impl/core/convert/trait.TryFrom.js new file mode 100644 index 00000000..c1333171 --- /dev/null +++ b/trait.impl/core/convert/trait.TryFrom.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["bytestring",[["impl TryFrom<&[u8; 0]> for ByteString"],["impl TryFrom<&[u8; 10]> for ByteString"],["impl TryFrom<&[u8; 11]> for ByteString"],["impl TryFrom<&[u8; 12]> for ByteString"],["impl TryFrom<&[u8; 13]> for ByteString"],["impl TryFrom<&[u8; 14]> for ByteString"],["impl TryFrom<&[u8; 15]> for ByteString"],["impl TryFrom<&[u8; 16]> for ByteString"],["impl TryFrom<&[u8; 17]> for ByteString"],["impl TryFrom<&[u8; 18]> for ByteString"],["impl TryFrom<&[u8; 19]> for ByteString"],["impl TryFrom<&[u8; 1]> for ByteString"],["impl TryFrom<&[u8; 20]> for ByteString"],["impl TryFrom<&[u8; 21]> for ByteString"],["impl TryFrom<&[u8; 22]> for ByteString"],["impl TryFrom<&[u8; 23]> for ByteString"],["impl TryFrom<&[u8; 24]> for ByteString"],["impl TryFrom<&[u8; 25]> for ByteString"],["impl TryFrom<&[u8; 26]> for ByteString"],["impl TryFrom<&[u8; 27]> for ByteString"],["impl TryFrom<&[u8; 28]> for ByteString"],["impl TryFrom<&[u8; 29]> for ByteString"],["impl TryFrom<&[u8; 2]> for ByteString"],["impl TryFrom<&[u8; 30]> for ByteString"],["impl TryFrom<&[u8; 31]> for ByteString"],["impl TryFrom<&[u8; 32]> for ByteString"],["impl TryFrom<&[u8; 3]> for ByteString"],["impl TryFrom<&[u8; 4]> for ByteString"],["impl TryFrom<&[u8; 5]> for ByteString"],["impl TryFrom<&[u8; 6]> for ByteString"],["impl TryFrom<&[u8; 7]> for ByteString"],["impl TryFrom<&[u8; 8]> for ByteString"],["impl TryFrom<&[u8; 9]> for ByteString"],["impl TryFrom<&[u8]> for ByteString"],["impl TryFrom<Vec<u8>> for ByteString"],["impl TryFrom<Bytes> for ByteString"],["impl TryFrom<BytesMut> for ByteString"],["impl TryFrom<[u8; 0]> for ByteString"],["impl TryFrom<[u8; 10]> for ByteString"],["impl TryFrom<[u8; 11]> for ByteString"],["impl TryFrom<[u8; 12]> for ByteString"],["impl TryFrom<[u8; 13]> for ByteString"],["impl TryFrom<[u8; 14]> for ByteString"],["impl TryFrom<[u8; 15]> for ByteString"],["impl TryFrom<[u8; 16]> for ByteString"],["impl TryFrom<[u8; 17]> for ByteString"],["impl TryFrom<[u8; 18]> for ByteString"],["impl TryFrom<[u8; 19]> for ByteString"],["impl TryFrom<[u8; 1]> for ByteString"],["impl TryFrom<[u8; 20]> for ByteString"],["impl TryFrom<[u8; 21]> for ByteString"],["impl TryFrom<[u8; 22]> for ByteString"],["impl TryFrom<[u8; 23]> for ByteString"],["impl TryFrom<[u8; 24]> for ByteString"],["impl TryFrom<[u8; 25]> for ByteString"],["impl TryFrom<[u8; 26]> for ByteString"],["impl TryFrom<[u8; 27]> for ByteString"],["impl TryFrom<[u8; 28]> for ByteString"],["impl TryFrom<[u8; 29]> for ByteString"],["impl TryFrom<[u8; 2]> for ByteString"],["impl TryFrom<[u8; 30]> for ByteString"],["impl TryFrom<[u8; 31]> for ByteString"],["impl TryFrom<[u8; 32]> for ByteString"],["impl TryFrom<[u8; 3]> for ByteString"],["impl TryFrom<[u8; 4]> for ByteString"],["impl TryFrom<[u8; 5]> for ByteString"],["impl TryFrom<[u8; 6]> for ByteString"],["impl TryFrom<[u8; 7]> for ByteString"],["impl TryFrom<[u8; 8]> for ByteString"],["impl TryFrom<[u8; 9]> for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[33256]} \ No newline at end of file diff --git a/trait.impl/core/default/trait.Default.js b/trait.impl/core/default/trait.Default.js new file mode 100644 index 00000000..d5338313 --- /dev/null +++ b/trait.impl/core/default/trait.Default.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Default for LinesCodec"]]],["actix_server",[["impl Default for ServerBuilder"]]],["actix_tls",[["impl Default for Connector"],["impl Default for ConnectorService"],["impl Default for Resolver"],["impl Default for ResolverService"],["impl Default for TcpConnector"],["impl Default for TcpConnectorService"]]],["bytestring",[["impl Default for ByteString"]]],["local_waker",[["impl Default for LocalWaker"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[295,308,1837,293,296]} \ No newline at end of file diff --git a/trait.impl/core/error/trait.Error.js b/trait.impl/core/error/trait.Error.js new file mode 100644 index 00000000..4f17a97c --- /dev/null +++ b/trait.impl/core/error/trait.Error.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl Error for ConnectError"],["impl<TlsErr, SvcErr> Error for TlsError<TlsErr, SvcErr>
where\n TlsErr: Error + 'static,\n SvcErr: Error + 'static,
"]]],["local_channel",[["impl<T> Error for SendError<T>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[957,318]} \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Debug.js b/trait.impl/core/fmt/trait.Debug.js new file mode 100644 index 00000000..11f4712d --- /dev/null +++ b/trait.impl/core/fmt/trait.Debug.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Debug for BytesCodec"],["impl Debug for LinesCodec"],["impl<T, U> Debug for Framed<T, U>
where\n T: Debug,\n U: Debug,
"],["impl<T: Debug, U: Debug> Debug for FramedParts<T, U>"]]],["actix_rt",[["impl Debug for Arbiter"],["impl Debug for ArbiterHandle"],["impl Debug for Runtime"],["impl Debug for System"],["impl Debug for SystemRunner"]]],["actix_server",[["impl Debug for MpTcp"],["impl Debug for ServerHandle"]]],["actix_tls",[["impl Debug for ConnectError"],["impl Debug for TcpConnector"],["impl Debug for TcpConnectorService"],["impl<R: Debug> Debug for ConnectInfo<R>"],["impl<R: Debug, IO: Debug> Debug for Connection<R, IO>"],["impl<TlsErr: Debug, SvcErr: Debug> Debug for TlsError<TlsErr, SvcErr>"]]],["actix_utils",[["impl Debug for Counter"],["impl Debug for CounterGuard"],["impl<F> Debug for PollFn<F>"],["impl<L: Debug, R: Debug> Debug for Either<L, R>"],["impl<T: Debug> Debug for Ready<T>"]]],["bytestring",[["impl Debug for ByteString"]]],["local_channel",[["impl<T> Debug for SendError<T>"],["impl<T: Debug> Debug for Receiver<T>"],["impl<T: Debug> Debug for Sender<T>"]]],["local_waker",[["impl Debug for LocalWaker"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1688,1290,536,2466,1825,279,1154,282]} \ No newline at end of file diff --git a/trait.impl/core/fmt/trait.Display.js b/trait.impl/core/fmt/trait.Display.js new file mode 100644 index 00000000..d9ad4658 --- /dev/null +++ b/trait.impl/core/fmt/trait.Display.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl Display for ConnectError"],["impl<R: Host> Display for ConnectInfo<R>"],["impl<TlsErr, SvcErr> Display for TlsError<TlsErr, SvcErr>"]]],["bytestring",[["impl Display for ByteString"]]],["local_channel",[["impl<T> Display for SendError<T>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1028,285,320]} \ No newline at end of file diff --git a/trait.impl/core/future/future/trait.Future.js b/trait.impl/core/future/future/trait.Future.js new file mode 100644 index 00000000..d0b554c5 --- /dev/null +++ b/trait.impl/core/future/future/trait.Future.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_server",[["impl Future for Server"]]],["actix_utils",[["impl<F, T> Future for PollFn<F>
where\n F: FnMut(&mut Context<'_>) -> Poll<T>,
"],["impl<L, R> Future for Either<L, R>
where\n L: Future,\n R: Future<Output = L::Output>,
"],["impl<T> Future for Ready<T>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[296,2034]} \ No newline at end of file diff --git a/trait.impl/core/hash/trait.Hash.js b/trait.impl/core/hash/trait.Hash.js new file mode 100644 index 00000000..c2e92598 --- /dev/null +++ b/trait.impl/core/hash/trait.Hash.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl<R: Hash> Hash for ConnectInfo<R>"]]],["bytestring",[["impl Hash for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[443,278]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Copy.js b/trait.impl/core/marker/trait.Copy.js new file mode 100644 index 00000000..60a6b3dc --- /dev/null +++ b/trait.impl/core/marker/trait.Copy.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Copy for BytesCodec"],["impl Copy for LinesCodec"]]],["actix_tls",[["impl Copy for TcpConnector"],["impl Copy for TcpConnectorService"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[551,627]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Freeze.js b/trait.impl/core/marker/trait.Freeze.js new file mode 100644 index 00000000..d66a37ad --- /dev/null +++ b/trait.impl/core/marker/trait.Freeze.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Freeze for BytesCodec",1,["actix_codec::bcodec::BytesCodec"]],["impl Freeze for LinesCodec",1,["actix_codec::lines::LinesCodec"]],["impl<T, U> Freeze for Framed<T, U>
where\n T: Freeze,\n U: Freeze,
",1,["actix_codec::framed::Framed"]],["impl<T, U> Freeze for FramedParts<T, U>
where\n T: Freeze,\n U: Freeze,
",1,["actix_codec::framed::FramedParts"]]]],["actix_rt",[["impl !Freeze for Runtime",1,["actix_rt::runtime::Runtime"]],["impl Freeze for Arbiter",1,["actix_rt::arbiter::Arbiter"]],["impl Freeze for ArbiterHandle",1,["actix_rt::arbiter::ArbiterHandle"]],["impl Freeze for System",1,["actix_rt::system::System"]],["impl Freeze for SystemRunner",1,["actix_rt::system::SystemRunner"]]]],["actix_server",[["impl Freeze for MpTcp",1,["actix_server::builder::MpTcp"]],["impl Freeze for Server",1,["actix_server::server::Server"]],["impl Freeze for ServerBuilder",1,["actix_server::builder::ServerBuilder"]],["impl Freeze for ServerHandle",1,["actix_server::handle::ServerHandle"]],["impl Freeze for TestServer",1,["actix_server::test_server::TestServer"]]]],["actix_service",[["impl<Cfg, Req, Res, Err, InitErr> Freeze for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>",1,["actix_service::boxed::BoxServiceFactory"]],["impl<T, S, Req> Freeze for ApplyTransform<T, S, Req>",1,["actix_service::transform::ApplyTransform"]]]],["actix_tls",[["impl Freeze for ConnectError",1,["actix_tls::connect::error::ConnectError"]],["impl Freeze for Acceptor",1,["actix_tls::accept::native_tls::Acceptor"]],["impl Freeze for AcceptorService",1,["actix_tls::accept::native_tls::AcceptorService"]],["impl Freeze for Acceptor",1,["actix_tls::accept::openssl::Acceptor"]],["impl Freeze for AcceptorService",1,["actix_tls::accept::openssl::AcceptorService"]],["impl Freeze for Acceptor",1,["actix_tls::accept::rustls_0_20::Acceptor"]],["impl Freeze for AcceptorService",1,["actix_tls::accept::rustls_0_20::AcceptorService"]],["impl Freeze for Acceptor",1,["actix_tls::accept::rustls_0_21::Acceptor"]],["impl Freeze for AcceptorService",1,["actix_tls::accept::rustls_0_21::AcceptorService"]],["impl Freeze for Acceptor",1,["actix_tls::accept::rustls_0_22::Acceptor"]],["impl Freeze for AcceptorService",1,["actix_tls::accept::rustls_0_22::AcceptorService"]],["impl Freeze for Acceptor",1,["actix_tls::accept::rustls_0_23::Acceptor"]],["impl Freeze for AcceptorService",1,["actix_tls::accept::rustls_0_23::AcceptorService"]],["impl Freeze for TlsConnector",1,["actix_tls::connect::native_tls::TlsConnector"]],["impl Freeze for TlsConnector",1,["actix_tls::connect::openssl::TlsConnector"]],["impl Freeze for TlsConnectorService",1,["actix_tls::connect::openssl::TlsConnectorService"]],["impl Freeze for TlsConnector",1,["actix_tls::connect::rustls_0_20::TlsConnector"]],["impl Freeze for TlsConnectorService",1,["actix_tls::connect::rustls_0_20::TlsConnectorService"]],["impl Freeze for TlsConnector",1,["actix_tls::connect::rustls_0_21::TlsConnector"]],["impl Freeze for TlsConnectorService",1,["actix_tls::connect::rustls_0_21::TlsConnectorService"]],["impl Freeze for TlsConnector",1,["actix_tls::connect::rustls_0_22::TlsConnector"]],["impl Freeze for TlsConnectorService",1,["actix_tls::connect::rustls_0_22::TlsConnectorService"]],["impl Freeze for TlsConnector",1,["actix_tls::connect::rustls_0_23::TlsConnector"]],["impl Freeze for TlsConnectorService",1,["actix_tls::connect::rustls_0_23::TlsConnectorService"]],["impl Freeze for Connector",1,["actix_tls::connect::connector::Connector"]],["impl Freeze for ConnectorService",1,["actix_tls::connect::connector::ConnectorService"]],["impl Freeze for Resolver",1,["actix_tls::connect::resolver::Resolver"]],["impl Freeze for ResolverService",1,["actix_tls::connect::resolver::ResolverService"]],["impl Freeze for TcpConnector",1,["actix_tls::connect::tcp::TcpConnector"]],["impl Freeze for TcpConnectorService",1,["actix_tls::connect::tcp::TcpConnectorService"]],["impl<IO> Freeze for TlsStream<IO>",1,["actix_tls::accept::native_tls::TlsStream"]],["impl<IO> Freeze for TlsStream<IO>",1,["actix_tls::accept::openssl::TlsStream"]],["impl<IO> Freeze for TlsStream<IO>
where\n IO: Freeze,
",1,["actix_tls::accept::rustls_0_20::TlsStream"]],["impl<IO> Freeze for TlsStream<IO>
where\n IO: Freeze,
",1,["actix_tls::accept::rustls_0_21::TlsStream"]],["impl<IO> Freeze for TlsStream<IO>
where\n IO: Freeze,
",1,["actix_tls::accept::rustls_0_22::TlsStream"]],["impl<IO> Freeze for TlsStream<IO>
where\n IO: Freeze,
",1,["actix_tls::accept::rustls_0_23::TlsStream"]],["impl<R> Freeze for ConnectInfo<R>
where\n R: Freeze,
",1,["actix_tls::connect::info::ConnectInfo"]],["impl<R, IO> Freeze for Connection<R, IO>
where\n R: Freeze,\n IO: Freeze,
",1,["actix_tls::connect::connection::Connection"]],["impl<TlsErr, SvcErr> Freeze for TlsError<TlsErr, SvcErr>
where\n TlsErr: Freeze,\n SvcErr: Freeze,
",1,["actix_tls::accept::TlsError"]]]],["actix_tracing",[["impl<S, F> Freeze for TracingService<S, F>
where\n S: Freeze,\n F: Freeze,
",1,["actix_tracing::TracingService"]],["impl<S, U, F> Freeze for TracingTransform<S, U, F>
where\n F: Freeze,
",1,["actix_tracing::TracingTransform"]]]],["actix_utils",[["impl Freeze for Counter",1,["actix_utils::counter::Counter"]],["impl Freeze for CounterGuard",1,["actix_utils::counter::CounterGuard"]],["impl<F> Freeze for PollFn<F>
where\n F: Freeze,
",1,["actix_utils::future::poll_fn::PollFn"]],["impl<L, R> Freeze for Either<L, R>
where\n L: Freeze,\n R: Freeze,
",1,["actix_utils::future::either::Either"]],["impl<T> Freeze for Ready<T>
where\n T: Freeze,
",1,["actix_utils::future::ready::Ready"]]]],["bytestring",[["impl !Freeze for ByteString",1,["bytestring::ByteString"]]]],["local_channel",[["impl<T> Freeze for Receiver<T>",1,["local_channel::mpsc::Receiver"]],["impl<T> Freeze for SendError<T>
where\n T: Freeze,
",1,["local_channel::mpsc::SendError"]],["impl<T> Freeze for Sender<T>",1,["local_channel::mpsc::Sender"]]]],["local_waker",[["impl !Freeze for LocalWaker",1,["local_waker::LocalWaker"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1956,1509,1574,817,15813,1243,2368,318,1205,322]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Send.js b/trait.impl/core/marker/trait.Send.js new file mode 100644 index 00000000..60f022c7 --- /dev/null +++ b/trait.impl/core/marker/trait.Send.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Send for BytesCodec",1,["actix_codec::bcodec::BytesCodec"]],["impl Send for LinesCodec",1,["actix_codec::lines::LinesCodec"]],["impl<T, U> Send for Framed<T, U>
where\n T: Send,\n U: Send,
",1,["actix_codec::framed::Framed"]],["impl<T, U> Send for FramedParts<T, U>
where\n T: Send,\n U: Send,
",1,["actix_codec::framed::FramedParts"]]]],["actix_rt",[["impl !Send for Runtime",1,["actix_rt::runtime::Runtime"]],["impl Send for Arbiter",1,["actix_rt::arbiter::Arbiter"]],["impl Send for ArbiterHandle",1,["actix_rt::arbiter::ArbiterHandle"]],["impl Send for System",1,["actix_rt::system::System"]],["impl Send for SystemRunner",1,["actix_rt::system::SystemRunner"]]]],["actix_server",[["impl Send for MpTcp",1,["actix_server::builder::MpTcp"]],["impl Send for Server",1,["actix_server::server::Server"]],["impl Send for ServerBuilder",1,["actix_server::builder::ServerBuilder"]],["impl Send for ServerHandle",1,["actix_server::handle::ServerHandle"]],["impl Send for TestServer",1,["actix_server::test_server::TestServer"]]]],["actix_service",[["impl<Cfg, Req, Res, Err, InitErr> !Send for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>",1,["actix_service::boxed::BoxServiceFactory"]],["impl<T, S, Req> !Send for ApplyTransform<T, S, Req>",1,["actix_service::transform::ApplyTransform"]]]],["actix_tls",[["impl !Send for ConnectError",1,["actix_tls::connect::error::ConnectError"]],["impl !Send for AcceptorService",1,["actix_tls::accept::native_tls::AcceptorService"]],["impl !Send for AcceptorService",1,["actix_tls::accept::openssl::AcceptorService"]],["impl !Send for AcceptorService",1,["actix_tls::accept::rustls_0_20::AcceptorService"]],["impl !Send for AcceptorService",1,["actix_tls::accept::rustls_0_21::AcceptorService"]],["impl !Send for AcceptorService",1,["actix_tls::accept::rustls_0_22::AcceptorService"]],["impl !Send for AcceptorService",1,["actix_tls::accept::rustls_0_23::AcceptorService"]],["impl !Send for Connector",1,["actix_tls::connect::connector::Connector"]],["impl !Send for ConnectorService",1,["actix_tls::connect::connector::ConnectorService"]],["impl !Send for Resolver",1,["actix_tls::connect::resolver::Resolver"]],["impl !Send for ResolverService",1,["actix_tls::connect::resolver::ResolverService"]],["impl Send for Acceptor",1,["actix_tls::accept::native_tls::Acceptor"]],["impl Send for Acceptor",1,["actix_tls::accept::openssl::Acceptor"]],["impl Send for Acceptor",1,["actix_tls::accept::rustls_0_20::Acceptor"]],["impl Send for Acceptor",1,["actix_tls::accept::rustls_0_21::Acceptor"]],["impl Send for Acceptor",1,["actix_tls::accept::rustls_0_22::Acceptor"]],["impl Send for Acceptor",1,["actix_tls::accept::rustls_0_23::Acceptor"]],["impl Send for TlsConnector",1,["actix_tls::connect::native_tls::TlsConnector"]],["impl Send for TlsConnector",1,["actix_tls::connect::openssl::TlsConnector"]],["impl Send for TlsConnectorService",1,["actix_tls::connect::openssl::TlsConnectorService"]],["impl Send for TlsConnector",1,["actix_tls::connect::rustls_0_20::TlsConnector"]],["impl Send for TlsConnectorService",1,["actix_tls::connect::rustls_0_20::TlsConnectorService"]],["impl Send for TlsConnector",1,["actix_tls::connect::rustls_0_21::TlsConnector"]],["impl Send for TlsConnectorService",1,["actix_tls::connect::rustls_0_21::TlsConnectorService"]],["impl Send for TlsConnector",1,["actix_tls::connect::rustls_0_22::TlsConnector"]],["impl Send for TlsConnectorService",1,["actix_tls::connect::rustls_0_22::TlsConnectorService"]],["impl Send for TlsConnector",1,["actix_tls::connect::rustls_0_23::TlsConnector"]],["impl Send for TlsConnectorService",1,["actix_tls::connect::rustls_0_23::TlsConnectorService"]],["impl Send for TcpConnector",1,["actix_tls::connect::tcp::TcpConnector"]],["impl Send for TcpConnectorService",1,["actix_tls::connect::tcp::TcpConnectorService"]],["impl<IO> Send for TlsStream<IO>
where\n IO: Send,
",1,["actix_tls::accept::native_tls::TlsStream"]],["impl<IO> Send for TlsStream<IO>
where\n IO: Send,
",1,["actix_tls::accept::openssl::TlsStream"]],["impl<IO> Send for TlsStream<IO>
where\n IO: Send,
",1,["actix_tls::accept::rustls_0_20::TlsStream"]],["impl<IO> Send for TlsStream<IO>
where\n IO: Send,
",1,["actix_tls::accept::rustls_0_21::TlsStream"]],["impl<IO> Send for TlsStream<IO>
where\n IO: Send,
",1,["actix_tls::accept::rustls_0_22::TlsStream"]],["impl<IO> Send for TlsStream<IO>
where\n IO: Send,
",1,["actix_tls::accept::rustls_0_23::TlsStream"]],["impl<R> Send for ConnectInfo<R>
where\n R: Send,
",1,["actix_tls::connect::info::ConnectInfo"]],["impl<R, IO> Send for Connection<R, IO>
where\n R: Send,\n IO: Send,
",1,["actix_tls::connect::connection::Connection"]],["impl<TlsErr, SvcErr> Send for TlsError<TlsErr, SvcErr>
where\n TlsErr: Send,\n SvcErr: Send,
",1,["actix_tls::accept::TlsError"]]]],["actix_tracing",[["impl<S, F> Send for TracingService<S, F>
where\n S: Send,\n F: Send,
",1,["actix_tracing::TracingService"]],["impl<S, U, F> Send for TracingTransform<S, U, F>
where\n F: Send,
",1,["actix_tracing::TracingTransform"]]]],["actix_utils",[["impl !Send for Counter",1,["actix_utils::counter::Counter"]],["impl !Send for CounterGuard",1,["actix_utils::counter::CounterGuard"]],["impl<F> Send for PollFn<F>
where\n F: Send,
",1,["actix_utils::future::poll_fn::PollFn"]],["impl<L, R> Send for Either<L, R>
where\n L: Send,\n R: Send,
",1,["actix_utils::future::either::Either"]],["impl<T> Send for Ready<T>
where\n T: Send,
",1,["actix_utils::future::ready::Ready"]]]],["bytestring",[["impl Send for ByteString",1,["bytestring::ByteString"]]]],["local_channel",[["impl<T> !Send for Receiver<T>",1,["local_channel::mpsc::Receiver"]],["impl<T> !Send for Sender<T>",1,["local_channel::mpsc::Sender"]],["impl<T> Send for SendError<T>
where\n T: Send,
",1,["local_channel::mpsc::SendError"]]]],["local_waker",[["impl !Send for LocalWaker",1,["local_waker::LocalWaker"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1908,1479,1544,807,15888,1213,2316,311,1183,316]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.StructuralPartialEq.js b/trait.impl/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 00000000..6093cbc9 --- /dev/null +++ b/trait.impl/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl<R> StructuralPartialEq for ConnectInfo<R>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[361]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Sync.js b/trait.impl/core/marker/trait.Sync.js new file mode 100644 index 00000000..4f5430bc --- /dev/null +++ b/trait.impl/core/marker/trait.Sync.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Sync for BytesCodec",1,["actix_codec::bcodec::BytesCodec"]],["impl Sync for LinesCodec",1,["actix_codec::lines::LinesCodec"]],["impl<T, U> Sync for Framed<T, U>
where\n T: Sync,\n U: Sync,
",1,["actix_codec::framed::Framed"]],["impl<T, U> Sync for FramedParts<T, U>
where\n T: Sync,\n U: Sync,
",1,["actix_codec::framed::FramedParts"]]]],["actix_rt",[["impl !Sync for Runtime",1,["actix_rt::runtime::Runtime"]],["impl Sync for Arbiter",1,["actix_rt::arbiter::Arbiter"]],["impl Sync for ArbiterHandle",1,["actix_rt::arbiter::ArbiterHandle"]],["impl Sync for System",1,["actix_rt::system::System"]],["impl Sync for SystemRunner",1,["actix_rt::system::SystemRunner"]]]],["actix_server",[["impl !Sync for Server",1,["actix_server::server::Server"]],["impl !Sync for ServerBuilder",1,["actix_server::builder::ServerBuilder"]],["impl Sync for MpTcp",1,["actix_server::builder::MpTcp"]],["impl Sync for ServerHandle",1,["actix_server::handle::ServerHandle"]],["impl Sync for TestServer",1,["actix_server::test_server::TestServer"]]]],["actix_service",[["impl<Cfg, Req, Res, Err, InitErr> !Sync for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>",1,["actix_service::boxed::BoxServiceFactory"]],["impl<T, S, Req> !Sync for ApplyTransform<T, S, Req>",1,["actix_service::transform::ApplyTransform"]]]],["actix_tls",[["impl !Sync for ConnectError",1,["actix_tls::connect::error::ConnectError"]],["impl !Sync for AcceptorService",1,["actix_tls::accept::native_tls::AcceptorService"]],["impl !Sync for AcceptorService",1,["actix_tls::accept::openssl::AcceptorService"]],["impl !Sync for AcceptorService",1,["actix_tls::accept::rustls_0_20::AcceptorService"]],["impl !Sync for AcceptorService",1,["actix_tls::accept::rustls_0_21::AcceptorService"]],["impl !Sync for AcceptorService",1,["actix_tls::accept::rustls_0_22::AcceptorService"]],["impl !Sync for AcceptorService",1,["actix_tls::accept::rustls_0_23::AcceptorService"]],["impl !Sync for Connector",1,["actix_tls::connect::connector::Connector"]],["impl !Sync for ConnectorService",1,["actix_tls::connect::connector::ConnectorService"]],["impl !Sync for Resolver",1,["actix_tls::connect::resolver::Resolver"]],["impl !Sync for ResolverService",1,["actix_tls::connect::resolver::ResolverService"]],["impl Sync for Acceptor",1,["actix_tls::accept::native_tls::Acceptor"]],["impl Sync for Acceptor",1,["actix_tls::accept::openssl::Acceptor"]],["impl Sync for Acceptor",1,["actix_tls::accept::rustls_0_20::Acceptor"]],["impl Sync for Acceptor",1,["actix_tls::accept::rustls_0_21::Acceptor"]],["impl Sync for Acceptor",1,["actix_tls::accept::rustls_0_22::Acceptor"]],["impl Sync for Acceptor",1,["actix_tls::accept::rustls_0_23::Acceptor"]],["impl Sync for TlsConnector",1,["actix_tls::connect::native_tls::TlsConnector"]],["impl Sync for TlsConnector",1,["actix_tls::connect::openssl::TlsConnector"]],["impl Sync for TlsConnectorService",1,["actix_tls::connect::openssl::TlsConnectorService"]],["impl Sync for TlsConnector",1,["actix_tls::connect::rustls_0_20::TlsConnector"]],["impl Sync for TlsConnectorService",1,["actix_tls::connect::rustls_0_20::TlsConnectorService"]],["impl Sync for TlsConnector",1,["actix_tls::connect::rustls_0_21::TlsConnector"]],["impl Sync for TlsConnectorService",1,["actix_tls::connect::rustls_0_21::TlsConnectorService"]],["impl Sync for TlsConnector",1,["actix_tls::connect::rustls_0_22::TlsConnector"]],["impl Sync for TlsConnectorService",1,["actix_tls::connect::rustls_0_22::TlsConnectorService"]],["impl Sync for TlsConnector",1,["actix_tls::connect::rustls_0_23::TlsConnector"]],["impl Sync for TlsConnectorService",1,["actix_tls::connect::rustls_0_23::TlsConnectorService"]],["impl Sync for TcpConnector",1,["actix_tls::connect::tcp::TcpConnector"]],["impl Sync for TcpConnectorService",1,["actix_tls::connect::tcp::TcpConnectorService"]],["impl<IO> Sync for TlsStream<IO>
where\n IO: Sync,
",1,["actix_tls::accept::native_tls::TlsStream"]],["impl<IO> Sync for TlsStream<IO>
where\n IO: Sync,
",1,["actix_tls::accept::openssl::TlsStream"]],["impl<IO> Sync for TlsStream<IO>
where\n IO: Sync,
",1,["actix_tls::accept::rustls_0_20::TlsStream"]],["impl<IO> Sync for TlsStream<IO>
where\n IO: Sync,
",1,["actix_tls::accept::rustls_0_21::TlsStream"]],["impl<IO> Sync for TlsStream<IO>
where\n IO: Sync,
",1,["actix_tls::accept::rustls_0_22::TlsStream"]],["impl<IO> Sync for TlsStream<IO>
where\n IO: Sync,
",1,["actix_tls::accept::rustls_0_23::TlsStream"]],["impl<R> Sync for ConnectInfo<R>
where\n R: Sync,
",1,["actix_tls::connect::info::ConnectInfo"]],["impl<R, IO> Sync for Connection<R, IO>
where\n R: Sync,\n IO: Sync,
",1,["actix_tls::connect::connection::Connection"]],["impl<TlsErr, SvcErr> Sync for TlsError<TlsErr, SvcErr>
where\n TlsErr: Sync,\n SvcErr: Sync,
",1,["actix_tls::accept::TlsError"]]]],["actix_tracing",[["impl<S, F> Sync for TracingService<S, F>
where\n S: Sync,\n F: Sync,
",1,["actix_tracing::TracingService"]],["impl<S, U, F> Sync for TracingTransform<S, U, F>
where\n F: Sync,
",1,["actix_tracing::TracingTransform"]]]],["actix_utils",[["impl !Sync for Counter",1,["actix_utils::counter::Counter"]],["impl !Sync for CounterGuard",1,["actix_utils::counter::CounterGuard"]],["impl<F> Sync for PollFn<F>
where\n F: Sync,
",1,["actix_utils::future::poll_fn::PollFn"]],["impl<L, R> Sync for Either<L, R>
where\n L: Sync,\n R: Sync,
",1,["actix_utils::future::either::Either"]],["impl<T> Sync for Ready<T>
where\n T: Sync,
",1,["actix_utils::future::ready::Ready"]]]],["bytestring",[["impl Sync for ByteString",1,["bytestring::ByteString"]]]],["local_channel",[["impl<T> !Sync for Receiver<T>",1,["local_channel::mpsc::Receiver"]],["impl<T> !Sync for Sender<T>",1,["local_channel::mpsc::Sender"]],["impl<T> Sync for SendError<T>
where\n T: Sync,
",1,["local_channel::mpsc::SendError"]]]],["local_waker",[["impl !Sync for LocalWaker",1,["local_waker::LocalWaker"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1908,1479,1546,807,15888,1213,2316,311,1183,316]} \ No newline at end of file diff --git a/trait.impl/core/marker/trait.Unpin.js b/trait.impl/core/marker/trait.Unpin.js new file mode 100644 index 00000000..385995cb --- /dev/null +++ b/trait.impl/core/marker/trait.Unpin.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Unpin for BytesCodec",1,["actix_codec::bcodec::BytesCodec"]],["impl Unpin for LinesCodec",1,["actix_codec::lines::LinesCodec"]],["impl<'__pin, T, U> Unpin for Framed<T, U>
where\n __Origin<'__pin, T, U>: Unpin,
"],["impl<T, U> Unpin for FramedParts<T, U>
where\n T: Unpin,\n U: Unpin,
",1,["actix_codec::framed::FramedParts"]]]],["actix_rt",[["impl Unpin for Arbiter",1,["actix_rt::arbiter::Arbiter"]],["impl Unpin for ArbiterHandle",1,["actix_rt::arbiter::ArbiterHandle"]],["impl Unpin for Runtime",1,["actix_rt::runtime::Runtime"]],["impl Unpin for System",1,["actix_rt::system::System"]],["impl Unpin for SystemRunner",1,["actix_rt::system::SystemRunner"]]]],["actix_server",[["impl Unpin for MpTcp",1,["actix_server::builder::MpTcp"]],["impl Unpin for Server",1,["actix_server::server::Server"]],["impl Unpin for ServerBuilder",1,["actix_server::builder::ServerBuilder"]],["impl Unpin for ServerHandle",1,["actix_server::handle::ServerHandle"]],["impl Unpin for TestServer",1,["actix_server::test_server::TestServer"]]]],["actix_service",[["impl<Cfg, Req, Res, Err, InitErr> Unpin for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>",1,["actix_service::boxed::BoxServiceFactory"]],["impl<T, S, Req> Unpin for ApplyTransform<T, S, Req>
where\n Req: Unpin,
",1,["actix_service::transform::ApplyTransform"]]]],["actix_tls",[["impl Unpin for ConnectError",1,["actix_tls::connect::error::ConnectError"]],["impl Unpin for Acceptor",1,["actix_tls::accept::native_tls::Acceptor"]],["impl Unpin for AcceptorService",1,["actix_tls::accept::native_tls::AcceptorService"]],["impl Unpin for Acceptor",1,["actix_tls::accept::openssl::Acceptor"]],["impl Unpin for AcceptorService",1,["actix_tls::accept::openssl::AcceptorService"]],["impl Unpin for Acceptor",1,["actix_tls::accept::rustls_0_20::Acceptor"]],["impl Unpin for AcceptorService",1,["actix_tls::accept::rustls_0_20::AcceptorService"]],["impl Unpin for Acceptor",1,["actix_tls::accept::rustls_0_21::Acceptor"]],["impl Unpin for AcceptorService",1,["actix_tls::accept::rustls_0_21::AcceptorService"]],["impl Unpin for Acceptor",1,["actix_tls::accept::rustls_0_22::Acceptor"]],["impl Unpin for AcceptorService",1,["actix_tls::accept::rustls_0_22::AcceptorService"]],["impl Unpin for Acceptor",1,["actix_tls::accept::rustls_0_23::Acceptor"]],["impl Unpin for AcceptorService",1,["actix_tls::accept::rustls_0_23::AcceptorService"]],["impl Unpin for TlsConnector",1,["actix_tls::connect::native_tls::TlsConnector"]],["impl Unpin for TlsConnector",1,["actix_tls::connect::openssl::TlsConnector"]],["impl Unpin for TlsConnectorService",1,["actix_tls::connect::openssl::TlsConnectorService"]],["impl Unpin for TlsConnector",1,["actix_tls::connect::rustls_0_20::TlsConnector"]],["impl Unpin for TlsConnectorService",1,["actix_tls::connect::rustls_0_20::TlsConnectorService"]],["impl Unpin for TlsConnector",1,["actix_tls::connect::rustls_0_21::TlsConnector"]],["impl Unpin for TlsConnectorService",1,["actix_tls::connect::rustls_0_21::TlsConnectorService"]],["impl Unpin for TlsConnector",1,["actix_tls::connect::rustls_0_22::TlsConnector"]],["impl Unpin for TlsConnectorService",1,["actix_tls::connect::rustls_0_22::TlsConnectorService"]],["impl Unpin for TlsConnector",1,["actix_tls::connect::rustls_0_23::TlsConnector"]],["impl Unpin for TlsConnectorService",1,["actix_tls::connect::rustls_0_23::TlsConnectorService"]],["impl Unpin for Connector",1,["actix_tls::connect::connector::Connector"]],["impl Unpin for ConnectorService",1,["actix_tls::connect::connector::ConnectorService"]],["impl Unpin for Resolver",1,["actix_tls::connect::resolver::Resolver"]],["impl Unpin for ResolverService",1,["actix_tls::connect::resolver::ResolverService"]],["impl Unpin for TcpConnector",1,["actix_tls::connect::tcp::TcpConnector"]],["impl Unpin for TcpConnectorService",1,["actix_tls::connect::tcp::TcpConnectorService"]],["impl<IO> Unpin for TlsStream<IO>
where\n IO: Unpin,
",1,["actix_tls::accept::native_tls::TlsStream"]],["impl<IO> Unpin for TlsStream<IO>
where\n IO: Unpin,
",1,["actix_tls::accept::openssl::TlsStream"]],["impl<IO> Unpin for TlsStream<IO>
where\n IO: Unpin,
",1,["actix_tls::accept::rustls_0_20::TlsStream"]],["impl<IO> Unpin for TlsStream<IO>
where\n IO: Unpin,
",1,["actix_tls::accept::rustls_0_21::TlsStream"]],["impl<IO> Unpin for TlsStream<IO>
where\n IO: Unpin,
",1,["actix_tls::accept::rustls_0_22::TlsStream"]],["impl<IO> Unpin for TlsStream<IO>
where\n IO: Unpin,
",1,["actix_tls::accept::rustls_0_23::TlsStream"]],["impl<R> Unpin for ConnectInfo<R>
where\n R: Unpin,
",1,["actix_tls::connect::info::ConnectInfo"]],["impl<R, IO> Unpin for Connection<R, IO>
where\n R: Unpin,\n IO: Unpin,
",1,["actix_tls::connect::connection::Connection"]],["impl<TlsErr, SvcErr> Unpin for TlsError<TlsErr, SvcErr>
where\n TlsErr: Unpin,\n SvcErr: Unpin,
",1,["actix_tls::accept::TlsError"]]]],["actix_tracing",[["impl<S, F> Unpin for TracingService<S, F>
where\n S: Unpin,\n F: Unpin,
",1,["actix_tracing::TracingService"]],["impl<S, U, F> Unpin for TracingTransform<S, U, F>
where\n F: Unpin,
",1,["actix_tracing::TracingTransform"]]]],["actix_utils",[["impl Unpin for Counter",1,["actix_utils::counter::Counter"]],["impl Unpin for CounterGuard"],["impl<'__pin, L, R> Unpin for Either<L, R>
where\n __Origin<'__pin, L, R>: Unpin,
"],["impl<F> Unpin for PollFn<F>
where\n F: Unpin,
",1,["actix_utils::future::poll_fn::PollFn"]],["impl<T> Unpin for Ready<T>"]]],["bytestring",[["impl Unpin for ByteString",1,["bytestring::ByteString"]]]],["local_channel",[["impl<T> Unpin for Receiver<T>"],["impl<T> Unpin for SendError<T>
where\n T: Unpin,
",1,["local_channel::mpsc::SendError"]],["impl<T> Unpin for Sender<T>"]]],["local_waker",[["impl Unpin for LocalWaker",1,["local_waker::LocalWaker"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1787,1493,1559,991,16027,1228,1929,314,1123,318]} \ No newline at end of file diff --git a/trait.impl/core/ops/deref/trait.Deref.js b/trait.impl/core/ops/deref/trait.Deref.js new file mode 100644 index 00000000..e78095d4 --- /dev/null +++ b/trait.impl/core/ops/deref/trait.Deref.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl<IO> Deref for TlsStream<IO>"],["impl<IO> Deref for TlsStream<IO>"],["impl<IO> Deref for TlsStream<IO>"],["impl<IO> Deref for TlsStream<IO>"],["impl<IO> Deref for TlsStream<IO>"],["impl<IO> Deref for TlsStream<IO>"],["impl<R, IO> Deref for Connection<R, IO>"]]],["bytestring",[["impl Deref for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[2301,292]} \ No newline at end of file diff --git a/trait.impl/core/ops/deref/trait.DerefMut.js b/trait.impl/core/ops/deref/trait.DerefMut.js new file mode 100644 index 00000000..a5d71413 --- /dev/null +++ b/trait.impl/core/ops/deref/trait.DerefMut.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_tls",[["impl<IO> DerefMut for TlsStream<IO>"],["impl<IO> DerefMut for TlsStream<IO>"],["impl<IO> DerefMut for TlsStream<IO>"],["impl<IO> DerefMut for TlsStream<IO>"],["impl<IO> DerefMut for TlsStream<IO>"],["impl<IO> DerefMut for TlsStream<IO>"],["impl<R, IO> DerefMut for Connection<R, IO>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[2364]} \ No newline at end of file diff --git a/trait.impl/core/ops/drop/trait.Drop.js b/trait.impl/core/ops/drop/trait.Drop.js new file mode 100644 index 00000000..0e124f06 --- /dev/null +++ b/trait.impl/core/ops/drop/trait.Drop.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_utils",[["impl Drop for CounterGuard"]]],["local_channel",[["impl<T> Drop for Receiver<T>"],["impl<T> Drop for Sender<T>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[312,612]} \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js new file mode 100644 index 00000000..e03021db --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl RefUnwindSafe for BytesCodec",1,["actix_codec::bcodec::BytesCodec"]],["impl RefUnwindSafe for LinesCodec",1,["actix_codec::lines::LinesCodec"]],["impl<T, U> RefUnwindSafe for Framed<T, U>
where\n T: RefUnwindSafe,\n U: RefUnwindSafe,
",1,["actix_codec::framed::Framed"]],["impl<T, U> RefUnwindSafe for FramedParts<T, U>
where\n T: RefUnwindSafe,\n U: RefUnwindSafe,
",1,["actix_codec::framed::FramedParts"]]]],["actix_rt",[["impl !RefUnwindSafe for Arbiter",1,["actix_rt::arbiter::Arbiter"]],["impl !RefUnwindSafe for Runtime",1,["actix_rt::runtime::Runtime"]],["impl RefUnwindSafe for ArbiterHandle",1,["actix_rt::arbiter::ArbiterHandle"]],["impl RefUnwindSafe for System",1,["actix_rt::system::System"]],["impl RefUnwindSafe for SystemRunner",1,["actix_rt::system::SystemRunner"]]]],["actix_server",[["impl !RefUnwindSafe for Server",1,["actix_server::server::Server"]],["impl !RefUnwindSafe for ServerBuilder",1,["actix_server::builder::ServerBuilder"]],["impl RefUnwindSafe for MpTcp",1,["actix_server::builder::MpTcp"]],["impl RefUnwindSafe for ServerHandle",1,["actix_server::handle::ServerHandle"]],["impl RefUnwindSafe for TestServer",1,["actix_server::test_server::TestServer"]]]],["actix_service",[["impl<Cfg, Req, Res, Err, InitErr> !RefUnwindSafe for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>",1,["actix_service::boxed::BoxServiceFactory"]],["impl<T, S, Req> RefUnwindSafe for ApplyTransform<T, S, Req>
where\n Req: RefUnwindSafe,\n T: RefUnwindSafe,\n S: RefUnwindSafe,
",1,["actix_service::transform::ApplyTransform"]]]],["actix_tls",[["impl !RefUnwindSafe for ConnectError",1,["actix_tls::connect::error::ConnectError"]],["impl !RefUnwindSafe for AcceptorService",1,["actix_tls::accept::native_tls::AcceptorService"]],["impl !RefUnwindSafe for AcceptorService",1,["actix_tls::accept::openssl::AcceptorService"]],["impl !RefUnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_20::Acceptor"]],["impl !RefUnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_20::AcceptorService"]],["impl !RefUnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_21::Acceptor"]],["impl !RefUnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_21::AcceptorService"]],["impl !RefUnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_22::Acceptor"]],["impl !RefUnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_22::AcceptorService"]],["impl !RefUnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_23::Acceptor"]],["impl !RefUnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_23::AcceptorService"]],["impl !RefUnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_20::TlsConnector"]],["impl !RefUnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_20::TlsConnectorService"]],["impl !RefUnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_21::TlsConnector"]],["impl !RefUnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_21::TlsConnectorService"]],["impl !RefUnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_22::TlsConnector"]],["impl !RefUnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_22::TlsConnectorService"]],["impl !RefUnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_23::TlsConnector"]],["impl !RefUnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_23::TlsConnectorService"]],["impl !RefUnwindSafe for Connector",1,["actix_tls::connect::connector::Connector"]],["impl !RefUnwindSafe for ConnectorService",1,["actix_tls::connect::connector::ConnectorService"]],["impl !RefUnwindSafe for Resolver",1,["actix_tls::connect::resolver::Resolver"]],["impl !RefUnwindSafe for ResolverService",1,["actix_tls::connect::resolver::ResolverService"]],["impl RefUnwindSafe for Acceptor",1,["actix_tls::accept::native_tls::Acceptor"]],["impl RefUnwindSafe for Acceptor",1,["actix_tls::accept::openssl::Acceptor"]],["impl RefUnwindSafe for TlsConnector",1,["actix_tls::connect::native_tls::TlsConnector"]],["impl RefUnwindSafe for TlsConnector",1,["actix_tls::connect::openssl::TlsConnector"]],["impl RefUnwindSafe for TlsConnectorService",1,["actix_tls::connect::openssl::TlsConnectorService"]],["impl RefUnwindSafe for TcpConnector",1,["actix_tls::connect::tcp::TcpConnector"]],["impl RefUnwindSafe for TcpConnectorService",1,["actix_tls::connect::tcp::TcpConnectorService"]],["impl<IO> !RefUnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_20::TlsStream"]],["impl<IO> !RefUnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_21::TlsStream"]],["impl<IO> !RefUnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_22::TlsStream"]],["impl<IO> !RefUnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_23::TlsStream"]],["impl<IO> RefUnwindSafe for TlsStream<IO>
where\n IO: RefUnwindSafe,
",1,["actix_tls::accept::native_tls::TlsStream"]],["impl<IO> RefUnwindSafe for TlsStream<IO>
where\n IO: RefUnwindSafe,
",1,["actix_tls::accept::openssl::TlsStream"]],["impl<R> RefUnwindSafe for ConnectInfo<R>
where\n R: RefUnwindSafe,
",1,["actix_tls::connect::info::ConnectInfo"]],["impl<R, IO> RefUnwindSafe for Connection<R, IO>
where\n R: RefUnwindSafe,\n IO: RefUnwindSafe,
",1,["actix_tls::connect::connection::Connection"]],["impl<TlsErr, SvcErr> RefUnwindSafe for TlsError<TlsErr, SvcErr>
where\n TlsErr: RefUnwindSafe,\n SvcErr: RefUnwindSafe,
",1,["actix_tls::accept::TlsError"]]]],["actix_tracing",[["impl<S, F> RefUnwindSafe for TracingService<S, F>
where\n S: RefUnwindSafe,\n F: RefUnwindSafe,
",1,["actix_tracing::TracingService"]],["impl<S, U, F> RefUnwindSafe for TracingTransform<S, U, F>
where\n F: RefUnwindSafe,
",1,["actix_tracing::TracingTransform"]]]],["actix_utils",[["impl !RefUnwindSafe for Counter",1,["actix_utils::counter::Counter"]],["impl !RefUnwindSafe for CounterGuard",1,["actix_utils::counter::CounterGuard"]],["impl<F> RefUnwindSafe for PollFn<F>
where\n F: RefUnwindSafe,
",1,["actix_utils::future::poll_fn::PollFn"]],["impl<L, R> RefUnwindSafe for Either<L, R>
where\n L: RefUnwindSafe,\n R: RefUnwindSafe,
",1,["actix_utils::future::either::Either"]],["impl<T> RefUnwindSafe for Ready<T>
where\n T: RefUnwindSafe,
",1,["actix_utils::future::ready::Ready"]]]],["bytestring",[["impl RefUnwindSafe for ByteString",1,["bytestring::ByteString"]]]],["local_channel",[["impl<T> !RefUnwindSafe for Receiver<T>",1,["local_channel::mpsc::Receiver"]],["impl<T> !RefUnwindSafe for Sender<T>",1,["local_channel::mpsc::Sender"]],["impl<T> RefUnwindSafe for SendError<T>
where\n T: RefUnwindSafe,
",1,["local_channel::mpsc::SendError"]]]],["local_waker",[["impl !RefUnwindSafe for LocalWaker",1,["local_waker::LocalWaker"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[2308,1730,1796,1519,17500,1463,2766,361,1383,366]} \ No newline at end of file diff --git a/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js new file mode 100644 index 00000000..1ae42e49 --- /dev/null +++ b/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl UnwindSafe for BytesCodec",1,["actix_codec::bcodec::BytesCodec"]],["impl UnwindSafe for LinesCodec",1,["actix_codec::lines::LinesCodec"]],["impl<T, U> UnwindSafe for Framed<T, U>
where\n T: UnwindSafe,\n U: UnwindSafe,
",1,["actix_codec::framed::Framed"]],["impl<T, U> UnwindSafe for FramedParts<T, U>
where\n T: UnwindSafe,\n U: UnwindSafe,
",1,["actix_codec::framed::FramedParts"]]]],["actix_rt",[["impl !UnwindSafe for Arbiter",1,["actix_rt::arbiter::Arbiter"]],["impl !UnwindSafe for Runtime",1,["actix_rt::runtime::Runtime"]],["impl UnwindSafe for ArbiterHandle",1,["actix_rt::arbiter::ArbiterHandle"]],["impl UnwindSafe for System",1,["actix_rt::system::System"]],["impl UnwindSafe for SystemRunner",1,["actix_rt::system::SystemRunner"]]]],["actix_server",[["impl !UnwindSafe for Server",1,["actix_server::server::Server"]],["impl !UnwindSafe for ServerBuilder",1,["actix_server::builder::ServerBuilder"]],["impl UnwindSafe for MpTcp",1,["actix_server::builder::MpTcp"]],["impl UnwindSafe for ServerHandle",1,["actix_server::handle::ServerHandle"]],["impl UnwindSafe for TestServer",1,["actix_server::test_server::TestServer"]]]],["actix_service",[["impl<Cfg, Req, Res, Err, InitErr> !UnwindSafe for BoxServiceFactory<Cfg, Req, Res, Err, InitErr>",1,["actix_service::boxed::BoxServiceFactory"]],["impl<T, S, Req> UnwindSafe for ApplyTransform<T, S, Req>
where\n Req: UnwindSafe,\n T: RefUnwindSafe,\n S: RefUnwindSafe,
",1,["actix_service::transform::ApplyTransform"]]]],["actix_tls",[["impl !UnwindSafe for ConnectError",1,["actix_tls::connect::error::ConnectError"]],["impl !UnwindSafe for AcceptorService",1,["actix_tls::accept::native_tls::AcceptorService"]],["impl !UnwindSafe for AcceptorService",1,["actix_tls::accept::openssl::AcceptorService"]],["impl !UnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_20::Acceptor"]],["impl !UnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_20::AcceptorService"]],["impl !UnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_21::Acceptor"]],["impl !UnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_21::AcceptorService"]],["impl !UnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_22::Acceptor"]],["impl !UnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_22::AcceptorService"]],["impl !UnwindSafe for Acceptor",1,["actix_tls::accept::rustls_0_23::Acceptor"]],["impl !UnwindSafe for AcceptorService",1,["actix_tls::accept::rustls_0_23::AcceptorService"]],["impl !UnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_20::TlsConnector"]],["impl !UnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_20::TlsConnectorService"]],["impl !UnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_21::TlsConnector"]],["impl !UnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_21::TlsConnectorService"]],["impl !UnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_22::TlsConnector"]],["impl !UnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_22::TlsConnectorService"]],["impl !UnwindSafe for TlsConnector",1,["actix_tls::connect::rustls_0_23::TlsConnector"]],["impl !UnwindSafe for TlsConnectorService",1,["actix_tls::connect::rustls_0_23::TlsConnectorService"]],["impl !UnwindSafe for Connector",1,["actix_tls::connect::connector::Connector"]],["impl !UnwindSafe for ConnectorService",1,["actix_tls::connect::connector::ConnectorService"]],["impl !UnwindSafe for Resolver",1,["actix_tls::connect::resolver::Resolver"]],["impl !UnwindSafe for ResolverService",1,["actix_tls::connect::resolver::ResolverService"]],["impl UnwindSafe for Acceptor",1,["actix_tls::accept::native_tls::Acceptor"]],["impl UnwindSafe for Acceptor",1,["actix_tls::accept::openssl::Acceptor"]],["impl UnwindSafe for TlsConnector",1,["actix_tls::connect::native_tls::TlsConnector"]],["impl UnwindSafe for TlsConnector",1,["actix_tls::connect::openssl::TlsConnector"]],["impl UnwindSafe for TlsConnectorService",1,["actix_tls::connect::openssl::TlsConnectorService"]],["impl UnwindSafe for TcpConnector",1,["actix_tls::connect::tcp::TcpConnector"]],["impl UnwindSafe for TcpConnectorService",1,["actix_tls::connect::tcp::TcpConnectorService"]],["impl<IO> !UnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_20::TlsStream"]],["impl<IO> !UnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_21::TlsStream"]],["impl<IO> !UnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_22::TlsStream"]],["impl<IO> !UnwindSafe for TlsStream<IO>",1,["actix_tls::accept::rustls_0_23::TlsStream"]],["impl<IO> UnwindSafe for TlsStream<IO>
where\n IO: UnwindSafe,
",1,["actix_tls::accept::native_tls::TlsStream"]],["impl<IO> UnwindSafe for TlsStream<IO>
where\n IO: UnwindSafe,
",1,["actix_tls::accept::openssl::TlsStream"]],["impl<R> UnwindSafe for ConnectInfo<R>
where\n R: UnwindSafe,
",1,["actix_tls::connect::info::ConnectInfo"]],["impl<R, IO> UnwindSafe for Connection<R, IO>
where\n R: UnwindSafe,\n IO: UnwindSafe,
",1,["actix_tls::connect::connection::Connection"]],["impl<TlsErr, SvcErr> UnwindSafe for TlsError<TlsErr, SvcErr>
where\n TlsErr: UnwindSafe,\n SvcErr: UnwindSafe,
",1,["actix_tls::accept::TlsError"]]]],["actix_tracing",[["impl<S, F> UnwindSafe for TracingService<S, F>
where\n S: UnwindSafe,\n F: UnwindSafe,
",1,["actix_tracing::TracingService"]],["impl<S, U, F> UnwindSafe for TracingTransform<S, U, F>
where\n F: UnwindSafe,
",1,["actix_tracing::TracingTransform"]]]],["actix_utils",[["impl !UnwindSafe for Counter",1,["actix_utils::counter::Counter"]],["impl !UnwindSafe for CounterGuard",1,["actix_utils::counter::CounterGuard"]],["impl<F> UnwindSafe for PollFn<F>
where\n F: UnwindSafe,
",1,["actix_utils::future::poll_fn::PollFn"]],["impl<L, R> UnwindSafe for Either<L, R>
where\n L: UnwindSafe,\n R: UnwindSafe,
",1,["actix_utils::future::either::Either"]],["impl<T> UnwindSafe for Ready<T>
where\n T: UnwindSafe,
",1,["actix_utils::future::ready::Ready"]]]],["bytestring",[["impl UnwindSafe for ByteString",1,["bytestring::ByteString"]]]],["local_channel",[["impl<T> !UnwindSafe for Receiver<T>",1,["local_channel::mpsc::Receiver"]],["impl<T> !UnwindSafe for Sender<T>",1,["local_channel::mpsc::Sender"]],["impl<T> UnwindSafe for SendError<T>
where\n T: UnwindSafe,
",1,["local_channel::mpsc::SendError"]]]],["local_waker",[["impl UnwindSafe for LocalWaker",1,["local_waker::LocalWaker"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[2236,1685,1751,1492,17086,1418,2685,352,1347,356]} \ No newline at end of file diff --git a/trait.impl/futures_core/stream/trait.Stream.js b/trait.impl/futures_core/stream/trait.Stream.js new file mode 100644 index 00000000..a71b2f73 --- /dev/null +++ b/trait.impl/futures_core/stream/trait.Stream.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl<T, U> Stream for Framed<T, U>
where\n T: AsyncRead,\n U: Decoder,
"]]],["local_channel",[["impl<T> Stream for Receiver<T>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[441,187]} \ No newline at end of file diff --git a/trait.impl/futures_sink/trait.Sink.js b/trait.impl/futures_sink/trait.Sink.js new file mode 100644 index 00000000..987a44a9 --- /dev/null +++ b/trait.impl/futures_sink/trait.Sink.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl<T, U, I> Sink<I> for Framed<T, U>
where\n T: AsyncWrite,\n U: Encoder<I>,\n U::Error: From<Error>,
"]]],["local_channel",[["impl<T> Sink<T> for Sender<T>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[901,188]} \ No newline at end of file diff --git a/trait.impl/serde/de/trait.Deserialize.js b/trait.impl/serde/de/trait.Deserialize.js new file mode 100644 index 00000000..882baec1 --- /dev/null +++ b/trait.impl/serde/de/trait.Deserialize.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["bytestring",[["impl<'de> Deserialize<'de> for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[314]} \ No newline at end of file diff --git a/trait.impl/serde/ser/trait.Serialize.js b/trait.impl/serde/ser/trait.Serialize.js new file mode 100644 index 00000000..d66c5e4e --- /dev/null +++ b/trait.impl/serde/ser/trait.Serialize.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["bytestring",[["impl Serialize for ByteString"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[288]} \ No newline at end of file diff --git a/trait.impl/tokio/io/async_read/trait.AsyncRead.js b/trait.impl/tokio/io/async_read/trait.AsyncRead.js new file mode 100644 index 00000000..1e1349f5 --- /dev/null +++ b/trait.impl/tokio/io/async_read/trait.AsyncRead.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[]],["actix_tls",[["impl<IO: ActixStream> AsyncRead for TlsStream<IO>"],["impl<IO: ActixStream> AsyncRead for TlsStream<IO>"],["impl<IO: ActixStream> AsyncRead for TlsStream<IO>"],["impl<IO: ActixStream> AsyncRead for TlsStream<IO>"],["impl<IO: ActixStream> AsyncRead for TlsStream<IO>"],["impl<IO: ActixStream> AsyncRead for TlsStream<IO>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[18,1260]} \ No newline at end of file diff --git a/trait.impl/tokio/io/async_write/trait.AsyncWrite.js b/trait.impl/tokio/io/async_write/trait.AsyncWrite.js new file mode 100644 index 00000000..2a0f23f7 --- /dev/null +++ b/trait.impl/tokio/io/async_write/trait.AsyncWrite.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[]],["actix_tls",[["impl<IO: ActixStream> AsyncWrite for TlsStream<IO>"],["impl<IO: ActixStream> AsyncWrite for TlsStream<IO>"],["impl<IO: ActixStream> AsyncWrite for TlsStream<IO>"],["impl<IO: ActixStream> AsyncWrite for TlsStream<IO>"],["impl<IO: ActixStream> AsyncWrite for TlsStream<IO>"],["impl<IO: ActixStream> AsyncWrite for TlsStream<IO>"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[18,1266]} \ No newline at end of file diff --git a/trait.impl/tokio_util/codec/decoder/trait.Decoder.js b/trait.impl/tokio_util/codec/decoder/trait.Decoder.js new file mode 100644 index 00000000..dcb5f8ef --- /dev/null +++ b/trait.impl/tokio_util/codec/decoder/trait.Decoder.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Decoder for BytesCodec"],["impl Decoder for LinesCodec"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[499]} \ No newline at end of file diff --git a/trait.impl/tokio_util/codec/encoder/trait.Encoder.js b/trait.impl/tokio_util/codec/encoder/trait.Encoder.js new file mode 100644 index 00000000..bb567de5 --- /dev/null +++ b/trait.impl/tokio_util/codec/encoder/trait.Encoder.js @@ -0,0 +1,9 @@ +(function() { + var implementors = Object.fromEntries([["actix_codec",[["impl Encoder<Bytes> for BytesCodec"],["impl<T: AsRef<str>> Encoder<T> for LinesCodec"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[774]} \ No newline at end of file diff --git a/type.impl/alloc/boxed/struct.Box.js b/type.impl/alloc/boxed/struct.Box.js new file mode 100644 index 00000000..610a0906 --- /dev/null +++ b/type.impl/alloc/boxed/struct.Box.js @@ -0,0 +1,9 @@ +(function() { + var type_impls = Object.fromEntries([["actix_service",[["
1.66.0 · source§

impl<T> AsFd for Box<T>
where\n T: AsFd + ?Sized,

source§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
","AsFd","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> AsMut<T> for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn as_mut(&mut self) -> &mut T

Converts this type into a mutable reference of the (usually inferred) input type.
","AsMut","actix_service::boxed::BoxService"],["
1.66.0 · source§

impl<T> AsRawFd for Box<T>
where\n T: AsRawFd,

source§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
","AsRawFd","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> AsRef<T> for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn as_ref(&self) -> &T

Converts this type into a shared reference of the (usually inferred) input type.
","AsRef","actix_service::boxed::BoxService"],["
source§

impl<Args, F, A> AsyncFn<Args> for Box<F, A>
where\n Args: Tuple,\n F: AsyncFn<Args> + ?Sized,\n A: Allocator,

source§

extern "rust-call" fn async_call(\n &self,\n args: Args,\n) -> <Box<F, A> as AsyncFnMut<Args>>::CallRefFuture<'_>

🔬This is a nightly-only experimental API. (async_fn_traits)
Call the AsyncFn, returning a future which may borrow from the called closure.
","AsyncFn","actix_service::boxed::BoxService"],["
source§

impl<Args, F, A> AsyncFnMut<Args> for Box<F, A>
where\n Args: Tuple,\n F: AsyncFnMut<Args> + ?Sized,\n A: Allocator,

source§

type CallRefFuture<'a> = <F as AsyncFnMut<Args>>::CallRefFuture<'a>\nwhere\n Box<F, A>: 'a

🔬This is a nightly-only experimental API. (async_fn_traits)
source§

extern "rust-call" fn async_call_mut(\n &mut self,\n args: Args,\n) -> <Box<F, A> as AsyncFnMut<Args>>::CallRefFuture<'_>

🔬This is a nightly-only experimental API. (async_fn_traits)
Call the AsyncFnMut, returning a future which may borrow from the called closure.
","AsyncFnMut","actix_service::boxed::BoxService"],["
source§

impl<Args, F, A> AsyncFnOnce<Args> for Box<F, A>
where\n Args: Tuple,\n F: AsyncFnOnce<Args> + ?Sized,\n A: Allocator,

source§

type Output = <F as AsyncFnOnce<Args>>::Output

🔬This is a nightly-only experimental API. (async_fn_traits)
Output type of the called closure’s future.
source§

type CallOnceFuture = <F as AsyncFnOnce<Args>>::CallOnceFuture

🔬This is a nightly-only experimental API. (async_fn_traits)
Future returned by AsyncFnOnce::async_call_once.
source§

extern "rust-call" fn async_call_once(\n self,\n args: Args,\n) -> <Box<F, A> as AsyncFnOnce<Args>>::CallOnceFuture

🔬This is a nightly-only experimental API. (async_fn_traits)
Call the AsyncFnOnce, returning a future which may move out of the called closure.
","AsyncFnOnce","actix_service::boxed::BoxService"],["
source§

impl<S> AsyncIterator for Box<S>
where\n S: AsyncIterator + Unpin + ?Sized,

source§

type Item = <S as AsyncIterator>::Item

🔬This is a nightly-only experimental API. (async_iterator)
The type of items yielded by the async iterator.
source§

fn poll_next(\n self: Pin<&mut Box<S>>,\n cx: &mut Context<'_>,\n) -> Poll<Option<<Box<S> as AsyncIterator>::Item>>

🔬This is a nightly-only experimental API. (async_iterator)
Attempts to pull out the next value of this async iterator, registering the\ncurrent task for wakeup if the value is not yet available, and returning\nNone if the async iterator is exhausted. Read more
source§

fn size_hint(&self) -> (usize, Option<usize>)

🔬This is a nightly-only experimental API. (async_iterator)
Returns the bounds on the remaining length of the async iterator. Read more
","AsyncIterator","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Borrow<T> for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
","Borrow","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> BorrowMut<T> for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
","BorrowMut","actix_service::boxed::BoxService"],["
source§

impl<T> Box<T>
where\n T: ?Sized,

1.36.0 · source

pub unsafe fn from_raw(raw: *mut T) -> Box<T>

Constructs a box from a raw pointer.

\n

After calling this function, the raw pointer is owned by the\nresulting Box. Specifically, the Box destructor will call\nthe destructor of T and free the allocated memory. For this\nto be safe, the memory must have been allocated in accordance\nwith the memory layout used by Box .

\n
§Safety
\n

This function is unsafe because improper use may lead to\nmemory problems. For example, a double-free may occur if the\nfunction is called twice on the same raw pointer.

\n

The safety conditions are described in the memory layout section.

\n
§Examples
\n

Recreate a Box which was previously converted to a raw pointer\nusing Box::into_raw:

\n\n
let x = Box::new(5);\nlet ptr = Box::into_raw(x);\nlet x = unsafe { Box::from_raw(ptr) };
\n

Manually create a Box from scratch by using the global allocator:

\n\n
use std::alloc::{alloc, Layout};\n\nunsafe {\n    let ptr = alloc(Layout::new::<i32>()) as *mut i32;\n    // In general .write is required to avoid attempting to destruct\n    // the (uninitialized) previous contents of `ptr`, though for this\n    // simple example `*ptr = 5` would have worked as well.\n    ptr.write(5);\n    let x = Box::from_raw(ptr);\n}
\n
source

pub unsafe fn from_non_null(ptr: NonNull<T>) -> Box<T>

🔬This is a nightly-only experimental API. (box_vec_non_null)

Constructs a box from a NonNull pointer.

\n

After calling this function, the NonNull pointer is owned by\nthe resulting Box. Specifically, the Box destructor will call\nthe destructor of T and free the allocated memory. For this\nto be safe, the memory must have been allocated in accordance\nwith the memory layout used by Box .

\n
§Safety
\n

This function is unsafe because improper use may lead to\nmemory problems. For example, a double-free may occur if the\nfunction is called twice on the same NonNull pointer.

\n

The safety conditions are described in the memory layout section.

\n
§Examples
\n

Recreate a Box which was previously converted to a NonNull\npointer using Box::into_non_null:

\n\n
#![feature(box_vec_non_null)]\n\nlet x = Box::new(5);\nlet non_null = Box::into_non_null(x);\nlet x = unsafe { Box::from_non_null(non_null) };
\n

Manually create a Box from scratch by using the global allocator:

\n\n
#![feature(box_vec_non_null)]\n\nuse std::alloc::{alloc, Layout};\nuse std::ptr::NonNull;\n\nunsafe {\n    let non_null = NonNull::new(alloc(Layout::new::<i32>()).cast::<i32>())\n        .expect(\"allocation failed\");\n    // In general .write is required to avoid attempting to destruct\n    // the (uninitialized) previous contents of `non_null`.\n    non_null.write(5);\n    let x = Box::from_non_null(non_null);\n}
\n
",0,"actix_service::boxed::BoxService"],["
source§

impl<T> Box<T>

1.36.0 · source

pub fn new(x: T) -> Box<T>

Allocates memory on the heap and then places x into it.

\n

This doesn’t actually allocate if T is zero-sized.

\n
§Examples
\n
let five = Box::new(5);
\n
1.82.0 · source

pub fn new_uninit() -> Box<MaybeUninit<T>>

Constructs a new box with uninitialized contents.

\n
§Examples
\n
let mut five = Box::<u32>::new_uninit();\n\nlet five = unsafe {\n    // Deferred initialization:\n    five.as_mut_ptr().write(5);\n\n    five.assume_init()\n};\n\nassert_eq!(*five, 5)
\n
source

pub fn new_zeroed() -> Box<MaybeUninit<T>>

🔬This is a nightly-only experimental API. (new_zeroed_alloc)

Constructs a new Box with uninitialized contents, with the memory\nbeing filled with 0 bytes.

\n

See MaybeUninit::zeroed for examples of correct and incorrect usage\nof this method.

\n
§Examples
\n
#![feature(new_zeroed_alloc)]\n\nlet zero = Box::<u32>::new_zeroed();\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0)
\n
1.36.0 · source

pub fn pin(x: T) -> Pin<Box<T>>

Constructs a new Pin<Box<T>>. If T does not implement Unpin, then\nx will be pinned in memory and unable to be moved.

\n

Constructing and pinning of the Box can also be done in two steps: Box::pin(x)\ndoes the same as Box::into_pin(Box::new(x)). Consider using\ninto_pin if you already have a Box<T>, or if you want to\nconstruct a (pinned) Box in a different way than with Box::new.

\n
source

pub fn try_new(x: T) -> Result<Box<T>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Allocates memory on the heap then places x into it,\nreturning an error if the allocation fails

\n

This doesn’t actually allocate if T is zero-sized.

\n
§Examples
\n
#![feature(allocator_api)]\n\nlet five = Box::try_new(5)?;
\n
source

pub fn try_new_uninit() -> Result<Box<MaybeUninit<T>>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new box with uninitialized contents on the heap,\nreturning an error if the allocation fails

\n
§Examples
\n
#![feature(allocator_api)]\n\nlet mut five = Box::<u32>::try_new_uninit()?;\n\nlet five = unsafe {\n    // Deferred initialization:\n    five.as_mut_ptr().write(5);\n\n    five.assume_init()\n};\n\nassert_eq!(*five, 5);
\n
source

pub fn try_new_zeroed() -> Result<Box<MaybeUninit<T>>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Box with uninitialized contents, with the memory\nbeing filled with 0 bytes on the heap

\n

See MaybeUninit::zeroed for examples of correct and incorrect usage\nof this method.

\n
§Examples
\n
#![feature(allocator_api)]\n\nlet zero = Box::<u32>::try_new_zeroed()?;\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0);
\n
",0,"actix_service::boxed::BoxService"],["
source§

impl<T, A> Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source

pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Box<T, A>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a box from a raw pointer in the given allocator.

\n

After calling this function, the raw pointer is owned by the\nresulting Box. Specifically, the Box destructor will call\nthe destructor of T and free the allocated memory. For this\nto be safe, the memory must have been allocated in accordance\nwith the memory layout used by Box .

\n
§Safety
\n

This function is unsafe because improper use may lead to\nmemory problems. For example, a double-free may occur if the\nfunction is called twice on the same raw pointer.

\n
§Examples
\n

Recreate a Box which was previously converted to a raw pointer\nusing Box::into_raw_with_allocator:

\n\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet x = Box::new_in(5, System);\nlet (ptr, alloc) = Box::into_raw_with_allocator(x);\nlet x = unsafe { Box::from_raw_in(ptr, alloc) };
\n

Manually create a Box from scratch by using the system allocator:

\n\n
#![feature(allocator_api, slice_ptr_get)]\n\nuse std::alloc::{Allocator, Layout, System};\n\nunsafe {\n    let ptr = System.allocate(Layout::new::<i32>())?.as_mut_ptr() as *mut i32;\n    // In general .write is required to avoid attempting to destruct\n    // the (uninitialized) previous contents of `ptr`, though for this\n    // simple example `*ptr = 5` would have worked as well.\n    ptr.write(5);\n    let x = Box::from_raw_in(ptr, System);\n}
\n
source

pub const unsafe fn from_non_null_in(raw: NonNull<T>, alloc: A) -> Box<T, A>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a box from a NonNull pointer in the given allocator.

\n

After calling this function, the NonNull pointer is owned by\nthe resulting Box. Specifically, the Box destructor will call\nthe destructor of T and free the allocated memory. For this\nto be safe, the memory must have been allocated in accordance\nwith the memory layout used by Box .

\n
§Safety
\n

This function is unsafe because improper use may lead to\nmemory problems. For example, a double-free may occur if the\nfunction is called twice on the same raw pointer.

\n
§Examples
\n

Recreate a Box which was previously converted to a NonNull pointer\nusing Box::into_non_null_with_allocator:

\n\n
#![feature(allocator_api, box_vec_non_null)]\n\nuse std::alloc::System;\n\nlet x = Box::new_in(5, System);\nlet (non_null, alloc) = Box::into_non_null_with_allocator(x);\nlet x = unsafe { Box::from_non_null_in(non_null, alloc) };
\n

Manually create a Box from scratch by using the system allocator:

\n\n
#![feature(allocator_api, box_vec_non_null, slice_ptr_get)]\n\nuse std::alloc::{Allocator, Layout, System};\n\nunsafe {\n    let non_null = System.allocate(Layout::new::<i32>())?.cast::<i32>();\n    // In general .write is required to avoid attempting to destruct\n    // the (uninitialized) previous contents of `non_null`.\n    non_null.write(5);\n    let x = Box::from_non_null_in(non_null, System);\n}
\n
1.36.0 · source

pub fn into_raw(b: Box<T, A>) -> *mut T

Consumes the Box, returning a wrapped raw pointer.

\n

The pointer will be properly aligned and non-null.

\n

After calling this function, the caller is responsible for the\nmemory previously managed by the Box. In particular, the\ncaller should properly destroy T and release the memory, taking\ninto account the memory layout used by Box. The easiest way to\ndo this is to convert the raw pointer back into a Box with the\nBox::from_raw function, allowing the Box destructor to perform\nthe cleanup.

\n

Note: this is an associated function, which means that you have\nto call it as Box::into_raw(b) instead of b.into_raw(). This\nis so that there is no conflict with a method on the inner type.

\n
§Examples
\n

Converting the raw pointer back into a Box with Box::from_raw\nfor automatic cleanup:

\n\n
let x = Box::new(String::from(\"Hello\"));\nlet ptr = Box::into_raw(x);\nlet x = unsafe { Box::from_raw(ptr) };
\n

Manual cleanup by explicitly running the destructor and deallocating\nthe memory:

\n\n
use std::alloc::{dealloc, Layout};\nuse std::ptr;\n\nlet x = Box::new(String::from(\"Hello\"));\nlet ptr = Box::into_raw(x);\nunsafe {\n    ptr::drop_in_place(ptr);\n    dealloc(ptr as *mut u8, Layout::new::<String>());\n}
\n

Note: This is equivalent to the following:

\n\n
let x = Box::new(String::from(\"Hello\"));\nlet ptr = Box::into_raw(x);\nunsafe {\n    drop(Box::from_raw(ptr));\n}
\n
source

pub fn into_non_null(b: Box<T, A>) -> NonNull<T>

🔬This is a nightly-only experimental API. (box_vec_non_null)

Consumes the Box, returning a wrapped NonNull pointer.

\n

The pointer will be properly aligned.

\n

After calling this function, the caller is responsible for the\nmemory previously managed by the Box. In particular, the\ncaller should properly destroy T and release the memory, taking\ninto account the memory layout used by Box. The easiest way to\ndo this is to convert the NonNull pointer back into a Box with the\nBox::from_non_null function, allowing the Box destructor to\nperform the cleanup.

\n

Note: this is an associated function, which means that you have\nto call it as Box::into_non_null(b) instead of b.into_non_null().\nThis is so that there is no conflict with a method on the inner type.

\n
§Examples
\n

Converting the NonNull pointer back into a Box with Box::from_non_null\nfor automatic cleanup:

\n\n
#![feature(box_vec_non_null)]\n\nlet x = Box::new(String::from(\"Hello\"));\nlet non_null = Box::into_non_null(x);\nlet x = unsafe { Box::from_non_null(non_null) };
\n

Manual cleanup by explicitly running the destructor and deallocating\nthe memory:

\n\n
#![feature(box_vec_non_null)]\n\nuse std::alloc::{dealloc, Layout};\n\nlet x = Box::new(String::from(\"Hello\"));\nlet non_null = Box::into_non_null(x);\nunsafe {\n    non_null.drop_in_place();\n    dealloc(non_null.as_ptr().cast::<u8>(), Layout::new::<String>());\n}
\n

Note: This is equivalent to the following:

\n\n
#![feature(box_vec_non_null)]\n\nlet x = Box::new(String::from(\"Hello\"));\nlet non_null = Box::into_non_null(x);\nunsafe {\n    drop(Box::from_non_null(non_null));\n}
\n
source

pub fn into_raw_with_allocator(b: Box<T, A>) -> (*mut T, A)

🔬This is a nightly-only experimental API. (allocator_api)

Consumes the Box, returning a wrapped raw pointer and the allocator.

\n

The pointer will be properly aligned and non-null.

\n

After calling this function, the caller is responsible for the\nmemory previously managed by the Box. In particular, the\ncaller should properly destroy T and release the memory, taking\ninto account the memory layout used by Box. The easiest way to\ndo this is to convert the raw pointer back into a Box with the\nBox::from_raw_in function, allowing the Box destructor to perform\nthe cleanup.

\n

Note: this is an associated function, which means that you have\nto call it as Box::into_raw_with_allocator(b) instead of b.into_raw_with_allocator(). This\nis so that there is no conflict with a method on the inner type.

\n
§Examples
\n

Converting the raw pointer back into a Box with Box::from_raw_in\nfor automatic cleanup:

\n\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet x = Box::new_in(String::from(\"Hello\"), System);\nlet (ptr, alloc) = Box::into_raw_with_allocator(x);\nlet x = unsafe { Box::from_raw_in(ptr, alloc) };
\n

Manual cleanup by explicitly running the destructor and deallocating\nthe memory:

\n\n
#![feature(allocator_api)]\n\nuse std::alloc::{Allocator, Layout, System};\nuse std::ptr::{self, NonNull};\n\nlet x = Box::new_in(String::from(\"Hello\"), System);\nlet (ptr, alloc) = Box::into_raw_with_allocator(x);\nunsafe {\n    ptr::drop_in_place(ptr);\n    let non_null = NonNull::new_unchecked(ptr);\n    alloc.deallocate(non_null.cast(), Layout::new::<String>());\n}
\n
source

pub fn into_non_null_with_allocator(b: Box<T, A>) -> (NonNull<T>, A)

🔬This is a nightly-only experimental API. (allocator_api)

Consumes the Box, returning a wrapped NonNull pointer and the allocator.

\n

The pointer will be properly aligned.

\n

After calling this function, the caller is responsible for the\nmemory previously managed by the Box. In particular, the\ncaller should properly destroy T and release the memory, taking\ninto account the memory layout used by Box. The easiest way to\ndo this is to convert the NonNull pointer back into a Box with the\nBox::from_non_null_in function, allowing the Box destructor to\nperform the cleanup.

\n

Note: this is an associated function, which means that you have\nto call it as Box::into_non_null_with_allocator(b) instead of\nb.into_non_null_with_allocator(). This is so that there is no\nconflict with a method on the inner type.

\n
§Examples
\n

Converting the NonNull pointer back into a Box with\nBox::from_non_null_in for automatic cleanup:

\n\n
#![feature(allocator_api, box_vec_non_null)]\n\nuse std::alloc::System;\n\nlet x = Box::new_in(String::from(\"Hello\"), System);\nlet (non_null, alloc) = Box::into_non_null_with_allocator(x);\nlet x = unsafe { Box::from_non_null_in(non_null, alloc) };
\n

Manual cleanup by explicitly running the destructor and deallocating\nthe memory:

\n\n
#![feature(allocator_api, box_vec_non_null)]\n\nuse std::alloc::{Allocator, Layout, System};\n\nlet x = Box::new_in(String::from(\"Hello\"), System);\nlet (non_null, alloc) = Box::into_non_null_with_allocator(x);\nunsafe {\n    non_null.drop_in_place();\n    alloc.deallocate(non_null.cast::<u8>(), Layout::new::<String>());\n}
\n
source

pub fn as_mut_ptr(b: &mut Box<T, A>) -> *mut T

🔬This is a nightly-only experimental API. (box_as_ptr)

Returns a raw mutable pointer to the Box’s contents.

\n

The caller must ensure that the Box outlives the pointer this\nfunction returns, or else it will end up dangling.

\n

This method guarantees that for the purpose of the aliasing model, this method\ndoes not materialize a reference to the underlying memory, and thus the returned pointer\nwill remain valid when mixed with other calls to as_ptr and as_mut_ptr.\nNote that calling other methods that materialize references to the memory\nmay still invalidate this pointer.\nSee the example below for how this guarantee can be used.

\n
§Examples
\n

Due to the aliasing guarantee, the following code is legal:

\n\n
#![feature(box_as_ptr)]\n\nunsafe {\n    let mut b = Box::new(0);\n    let ptr1 = Box::as_mut_ptr(&mut b);\n    ptr1.write(1);\n    let ptr2 = Box::as_mut_ptr(&mut b);\n    ptr2.write(2);\n    // Notably, the write to `ptr2` did *not* invalidate `ptr1`:\n    ptr1.write(3);\n}
\n
source

pub fn as_ptr(b: &Box<T, A>) -> *const T

🔬This is a nightly-only experimental API. (box_as_ptr)

Returns a raw pointer to the Box’s contents.

\n

The caller must ensure that the Box outlives the pointer this\nfunction returns, or else it will end up dangling.

\n

The caller must also ensure that the memory the pointer (non-transitively) points to\nis never written to (except inside an UnsafeCell) using this pointer or any pointer\nderived from it. If you need to mutate the contents of the Box, use as_mut_ptr.

\n

This method guarantees that for the purpose of the aliasing model, this method\ndoes not materialize a reference to the underlying memory, and thus the returned pointer\nwill remain valid when mixed with other calls to as_ptr and as_mut_ptr.\nNote that calling other methods that materialize mutable references to the memory,\nas well as writing to this memory, may still invalidate this pointer.\nSee the example below for how this guarantee can be used.

\n
§Examples
\n

Due to the aliasing guarantee, the following code is legal:

\n\n
#![feature(box_as_ptr)]\n\nunsafe {\n    let mut v = Box::new(0);\n    let ptr1 = Box::as_ptr(&v);\n    let ptr2 = Box::as_mut_ptr(&mut v);\n    let _val = ptr2.read();\n    // No write to this memory has happened yet, so `ptr1` is still valid.\n    let _val = ptr1.read();\n    // However, once we do a write...\n    ptr2.write(1);\n    // ... `ptr1` is no longer valid.\n    // This would be UB: let _val = ptr1.read();\n}
\n
source

pub const fn allocator(b: &Box<T, A>) -> &A

🔬This is a nightly-only experimental API. (allocator_api)

Returns a reference to the underlying allocator.

\n

Note: this is an associated function, which means that you have\nto call it as Box::allocator(&b) instead of b.allocator(). This\nis so that there is no conflict with a method on the inner type.

\n
1.36.0 · source

pub fn leak<'a>(b: Box<T, A>) -> &'a mut T
where\n A: 'a,

Consumes and leaks the Box, returning a mutable reference,\n&'a mut T.

\n

Note that the type T must outlive the chosen lifetime 'a. If the type\nhas only static references, or none at all, then this may be chosen to be\n'static.

\n

This function is mainly useful for data that lives for the remainder of\nthe program’s life. Dropping the returned reference will cause a memory\nleak. If this is not acceptable, the reference should first be wrapped\nwith the Box::from_raw function producing a Box. This Box can\nthen be dropped which will properly destroy T and release the\nallocated memory.

\n

Note: this is an associated function, which means that you have\nto call it as Box::leak(b) instead of b.leak(). This\nis so that there is no conflict with a method on the inner type.

\n
§Examples
\n

Simple usage:

\n\n
let x = Box::new(41);\nlet static_ref: &'static mut usize = Box::leak(x);\n*static_ref += 1;\nassert_eq!(*static_ref, 42);
\n

Unsized data:

\n\n
let x = vec![1, 2, 3].into_boxed_slice();\nlet static_ref = Box::leak(x);\nstatic_ref[0] = 4;\nassert_eq!(*static_ref, [4, 2, 3]);
\n
1.63.0 (const: unstable) · source

pub fn into_pin(boxed: Box<T, A>) -> Pin<Box<T, A>>
where\n A: 'static,

Converts a Box<T> into a Pin<Box<T>>. If T does not implement Unpin, then\n*boxed will be pinned in memory and unable to be moved.

\n

This conversion does not allocate on the heap and happens in place.

\n

This is also available via From.

\n

Constructing and pinning a Box with Box::into_pin(Box::new(x))\ncan also be written more concisely using Box::pin(x).\nThis into_pin method is useful if you already have a Box<T>, or you are\nconstructing a (pinned) Box in a different way than with Box::new.

\n
§Notes
\n

It’s not recommended that crates add an impl like From<Box<T>> for Pin<T>,\nas it’ll introduce an ambiguity when calling Pin::from.\nA demonstration of such a poor impl is shown below.

\n\n
struct Foo; // A type defined in this crate.\nimpl From<Box<()>> for Pin<Foo> {\n    fn from(_: Box<()>) -> Pin<Foo> {\n        Pin::new(Foo)\n    }\n}\n\nlet foo = Box::new(());\nlet bar = Pin::from(foo);
\n
",0,"actix_service::boxed::BoxService"],["
source§

impl<T, A> Box<T, A>
where\n A: Allocator,

source

pub fn new_in(x: T, alloc: A) -> Box<T, A>
where\n A: Allocator,

🔬This is a nightly-only experimental API. (allocator_api)

Allocates memory in the given allocator then places x into it.

\n

This doesn’t actually allocate if T is zero-sized.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet five = Box::new_in(5, System);
\n
source

pub fn try_new_in(x: T, alloc: A) -> Result<Box<T, A>, AllocError>
where\n A: Allocator,

🔬This is a nightly-only experimental API. (allocator_api)

Allocates memory in the given allocator then places x into it,\nreturning an error if the allocation fails

\n

This doesn’t actually allocate if T is zero-sized.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet five = Box::try_new_in(5, System)?;
\n
source

pub fn new_uninit_in(alloc: A) -> Box<MaybeUninit<T>, A>
where\n A: Allocator,

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new box with uninitialized contents in the provided allocator.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet mut five = Box::<u32, _>::new_uninit_in(System);\n\nlet five = unsafe {\n    // Deferred initialization:\n    five.as_mut_ptr().write(5);\n\n    five.assume_init()\n};\n\nassert_eq!(*five, 5)
\n
source

pub fn try_new_uninit_in(alloc: A) -> Result<Box<MaybeUninit<T>, A>, AllocError>
where\n A: Allocator,

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new box with uninitialized contents in the provided allocator,\nreturning an error if the allocation fails

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet mut five = Box::<u32, _>::try_new_uninit_in(System)?;\n\nlet five = unsafe {\n    // Deferred initialization:\n    five.as_mut_ptr().write(5);\n\n    five.assume_init()\n};\n\nassert_eq!(*five, 5);
\n
source

pub fn new_zeroed_in(alloc: A) -> Box<MaybeUninit<T>, A>
where\n A: Allocator,

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Box with uninitialized contents, with the memory\nbeing filled with 0 bytes in the provided allocator.

\n

See MaybeUninit::zeroed for examples of correct and incorrect usage\nof this method.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet zero = Box::<u32, _>::new_zeroed_in(System);\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0)
\n
source

pub fn try_new_zeroed_in(alloc: A) -> Result<Box<MaybeUninit<T>, A>, AllocError>
where\n A: Allocator,

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Box with uninitialized contents, with the memory\nbeing filled with 0 bytes in the provided allocator,\nreturning an error if the allocation fails,

\n

See MaybeUninit::zeroed for examples of correct and incorrect usage\nof this method.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::alloc::System;\n\nlet zero = Box::<u32, _>::try_new_zeroed_in(System)?;\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0);
\n
source

pub fn pin_in(x: T, alloc: A) -> Pin<Box<T, A>>
where\n A: 'static + Allocator,

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Pin<Box<T, A>>. If T does not implement Unpin, then\nx will be pinned in memory and unable to be moved.

\n

Constructing and pinning of the Box can also be done in two steps: Box::pin_in(x, alloc)\ndoes the same as Box::into_pin(Box::new_in(x, alloc)). Consider using\ninto_pin if you already have a Box<T, A>, or if you want to\nconstruct a (pinned) Box in a different way than with Box::new_in.

\n
source

pub fn into_boxed_slice(boxed: Box<T, A>) -> Box<[T], A>

🔬This is a nightly-only experimental API. (box_into_boxed_slice)

Converts a Box<T> into a Box<[T]>

\n

This conversion does not allocate on the heap and happens in place.

\n
source

pub fn into_inner(boxed: Box<T, A>) -> T

🔬This is a nightly-only experimental API. (box_into_inner)

Consumes the Box, returning the wrapped value.

\n
§Examples
\n
#![feature(box_into_inner)]\n\nlet c = Box::new(5);\n\nassert_eq!(Box::into_inner(c), 5);
\n
",0,"actix_service::boxed::BoxService"],["
1.0.0 · source§

impl<B> BufRead for Box<B>
where\n B: BufRead + ?Sized,

source§

fn fill_buf(&mut self) -> Result<&[u8], Error>

Returns the contents of the internal buffer, filling it with more data\nfrom the inner reader if it is empty. Read more
source§

fn consume(&mut self, amt: usize)

Tells this buffer that amt bytes have been consumed from the buffer,\nso they should no longer be returned in calls to read. Read more
source§

fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize, Error>

Reads all bytes into buf until the delimiter byte or EOF is reached. Read more
source§

fn read_line(&mut self, buf: &mut String) -> Result<usize, Error>

Reads all bytes until a newline (the 0xA byte) is reached, and append\nthem to the provided String buffer. Read more
source§

fn has_data_left(&mut self) -> Result<bool, Error>

🔬This is a nightly-only experimental API. (buf_read_has_data_left)
Checks if the underlying Read has any data left to be read. Read more
source§

fn skip_until(&mut self, byte: u8) -> Result<usize, Error>

🔬This is a nightly-only experimental API. (bufread_skip_until)
Skips all bytes until the delimiter byte or EOF is reached. Read more
1.0.0 · source§

fn split(self, byte: u8) -> Split<Self>
where\n Self: Sized,

Returns an iterator over the contents of this reader split on the byte\nbyte. Read more
1.0.0 · source§

fn lines(self) -> Lines<Self>
where\n Self: Sized,

Returns an iterator over the lines of this reader. Read more
","BufRead","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Clone for Box<T, A>
where\n T: Clone,\n A: Allocator + Clone,

source§

fn clone(&self) -> Box<T, A>

Returns a new box with a clone() of this box’s contents.

\n
§Examples
\n
let x = Box::new(5);\nlet y = x.clone();\n\n// The value is the same\nassert_eq!(x, y);\n\n// But they are unique objects\nassert_ne!(&*x as *const i32, &*y as *const i32);
\n
source§

fn clone_from(&mut self, source: &Box<T, A>)

Copies source’s contents into self without creating a new allocation.

\n
§Examples
\n
let x = Box::new(5);\nlet mut y = Box::new(10);\nlet yp: *const i32 = &*y;\n\ny.clone_from(&x);\n\n// The value is the same\nassert_eq!(x, y);\n\n// And no allocation occurred\nassert_eq!(yp, &*y);
\n
","Clone","actix_service::boxed::BoxService"],["
source§

impl<G, R, A> Coroutine<R> for Box<G, A>
where\n G: Coroutine<R> + Unpin + ?Sized,\n A: Allocator,

source§

type Yield = <G as Coroutine<R>>::Yield

🔬This is a nightly-only experimental API. (coroutine_trait)
The type of value this coroutine yields. Read more
source§

type Return = <G as Coroutine<R>>::Return

🔬This is a nightly-only experimental API. (coroutine_trait)
The type of value this coroutine returns. Read more
source§

fn resume(\n self: Pin<&mut Box<G, A>>,\n arg: R,\n) -> CoroutineState<<Box<G, A> as Coroutine<R>>::Yield, <Box<G, A> as Coroutine<R>>::Return>

🔬This is a nightly-only experimental API. (coroutine_trait)
Resumes the execution of this coroutine. Read more
","Coroutine","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Debug for Box<T, A>
where\n T: Debug + ?Sized,\n A: Allocator,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Debug","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T> Default for Box<T>
where\n T: Default,

source§

fn default() -> Box<T>

Creates a Box<T>, with the Default value for T.

\n
","Default","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Deref for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

type Target = T

The resulting type after dereferencing.
source§

fn deref(&self) -> &T

Dereferences the value.
","Deref","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> DerefMut for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn deref_mut(&mut self) -> &mut T

Mutably dereferences the value.
","DerefMut","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Display for Box<T, A>
where\n T: Display + ?Sized,\n A: Allocator,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Display","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<I, A> DoubleEndedIterator for Box<I, A>
where\n I: DoubleEndedIterator + ?Sized,\n A: Allocator,

source§

fn next_back(&mut self) -> Option<<I as Iterator>::Item>

Removes and returns an element from the end of the iterator. Read more
source§

fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>

Returns the nth element from the end of the iterator. Read more
source§

fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>>

🔬This is a nightly-only experimental API. (iter_advance_by)
Advances the iterator from the back by n elements. Read more
1.27.0 · source§

fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
where\n Self: Sized,\n F: FnMut(B, Self::Item) -> R,\n R: Try<Output = B>,

This is the reverse version of Iterator::try_fold(): it takes\nelements starting from the back of the iterator. Read more
1.27.0 · source§

fn rfold<B, F>(self, init: B, f: F) -> B
where\n Self: Sized,\n F: FnMut(B, Self::Item) -> B,

An iterator method that reduces the iterator’s elements to a single,\nfinal value, starting from the back. Read more
1.27.0 · source§

fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where\n Self: Sized,\n P: FnMut(&Self::Item) -> bool,

Searches for an element of an iterator from the back that satisfies a predicate. Read more
","DoubleEndedIterator","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Drop for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
","Drop","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T> Error for Box<T>
where\n T: Error,

source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
source§

fn provide<'b>(&'b self, request: &mut Request<'b>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
","Error","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<I, A> ExactSizeIterator for Box<I, A>
where\n I: ExactSizeIterator + ?Sized,\n A: Allocator,

source§

fn len(&self) -> usize

Returns the exact remaining length of the iterator. Read more
source§

fn is_empty(&self) -> bool

🔬This is a nightly-only experimental API. (exact_size_is_empty)
Returns true if the iterator is empty. Read more
","ExactSizeIterator","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<Args, F, A> Fn<Args> for Box<F, A>
where\n Args: Tuple,\n F: Fn<Args> + ?Sized,\n A: Allocator,

source§

extern "rust-call" fn call(\n &self,\n args: Args,\n) -> <Box<F, A> as FnOnce<Args>>::Output

🔬This is a nightly-only experimental API. (fn_traits)
Performs the call operation.
","Fn","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<Args, F, A> FnMut<Args> for Box<F, A>
where\n Args: Tuple,\n F: FnMut<Args> + ?Sized,\n A: Allocator,

source§

extern "rust-call" fn call_mut(\n &mut self,\n args: Args,\n) -> <Box<F, A> as FnOnce<Args>>::Output

🔬This is a nightly-only experimental API. (fn_traits)
Performs the call operation.
","FnMut","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<Args, F, A> FnOnce<Args> for Box<F, A>
where\n Args: Tuple,\n F: FnOnce<Args> + ?Sized,\n A: Allocator,

source§

type Output = <F as FnOnce<Args>>::Output

The returned type after the call operator is used.
source§

extern "rust-call" fn call_once(\n self,\n args: Args,\n) -> <Box<F, A> as FnOnce<Args>>::Output

🔬This is a nightly-only experimental API. (fn_traits)
Performs the call operation.
","FnOnce","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T> From<T> for Box<T>

source§

fn from(t: T) -> Box<T>

Converts a T into a Box<T>

\n

The conversion allocates on the heap and moves t\nfrom the stack into it.

\n
§Examples
\n
let x = 5;\nlet boxed = Box::new(5);\n\nassert_eq!(Box::from(x), boxed);
\n
","From","actix_service::boxed::BoxService"],["
§

impl<F> FusedFuture for Box<F>
where\n F: FusedFuture + Unpin + ?Sized,

§

fn is_terminated(&self) -> bool

Returns true if the underlying future should no longer be polled.
","FusedFuture","actix_service::boxed::BoxService"],["
§

impl<S> FusedStream for Box<S>
where\n S: FusedStream + Unpin + ?Sized,

§

fn is_terminated(&self) -> bool

Returns true if the stream should no longer be polled.
","FusedStream","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<F, A> Future for Box<F, A>
where\n F: Future + Unpin + ?Sized,\n A: Allocator,

source§

type Output = <F as Future>::Output

The type of value produced on completion.
source§

fn poll(\n self: Pin<&mut Box<F, A>>,\n cx: &mut Context<'_>,\n) -> Poll<<Box<F, A> as Future>::Output>

Attempts to resolve the future to a final value, registering\nthe current task for wakeup if the value is not yet available. Read more
","Future","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Hash for Box<T, A>
where\n T: Hash + ?Sized,\n A: Allocator,

source§

fn hash<H>(&self, state: &mut H)
where\n H: Hasher,

Feeds this value into the given Hasher. Read more
1.6.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where\n H: Hasher,\n Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
","Hash","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Hasher for Box<T, A>
where\n T: Hasher + ?Sized,\n A: Allocator,

source§

fn finish(&self) -> u64

Returns the hash value for the values written so far. Read more
source§

fn write(&mut self, bytes: &[u8])

Writes some data into this Hasher. Read more
source§

fn write_u8(&mut self, i: u8)

Writes a single u8 into this hasher.
source§

fn write_u16(&mut self, i: u16)

Writes a single u16 into this hasher.
source§

fn write_u32(&mut self, i: u32)

Writes a single u32 into this hasher.
source§

fn write_u64(&mut self, i: u64)

Writes a single u64 into this hasher.
source§

fn write_u128(&mut self, i: u128)

Writes a single u128 into this hasher.
source§

fn write_usize(&mut self, i: usize)

Writes a single usize into this hasher.
source§

fn write_i8(&mut self, i: i8)

Writes a single i8 into this hasher.
source§

fn write_i16(&mut self, i: i16)

Writes a single i16 into this hasher.
source§

fn write_i32(&mut self, i: i32)

Writes a single i32 into this hasher.
source§

fn write_i64(&mut self, i: i64)

Writes a single i64 into this hasher.
source§

fn write_i128(&mut self, i: i128)

Writes a single i128 into this hasher.
source§

fn write_isize(&mut self, i: isize)

Writes a single isize into this hasher.
source§

fn write_length_prefix(&mut self, len: usize)

🔬This is a nightly-only experimental API. (hasher_prefixfree_extras)
Writes a length prefix into this hasher, as part of being prefix-free. Read more
source§

fn write_str(&mut self, s: &str)

🔬This is a nightly-only experimental API. (hasher_prefixfree_extras)
Writes a single str into this hasher. Read more
","Hasher","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<I, A> Iterator for Box<I, A>
where\n I: Iterator + ?Sized,\n A: Allocator,

source§

type Item = <I as Iterator>::Item

The type of the elements being iterated over.
source§

fn next(&mut self) -> Option<<I as Iterator>::Item>

Advances the iterator and returns the next value. Read more
source§

fn size_hint(&self) -> (usize, Option<usize>)

Returns the bounds on the remaining length of the iterator. Read more
source§

fn nth(&mut self, n: usize) -> Option<<I as Iterator>::Item>

Returns the nth element of the iterator. Read more
source§

fn last(self) -> Option<<I as Iterator>::Item>

Consumes the iterator, returning the last element. Read more
source§

fn next_chunk<const N: usize>(\n &mut self,\n) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>
where\n Self: Sized,

🔬This is a nightly-only experimental API. (iter_next_chunk)
Advances the iterator and returns an array containing the next N values. Read more
1.6.0 · source§

fn count(self) -> usize
where\n Self: Sized,

Consumes the iterator, counting the number of iterations and returning it. Read more
source§

fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>

🔬This is a nightly-only experimental API. (iter_advance_by)
Advances the iterator by n elements. Read more
1.28.0 · source§

fn step_by(self, step: usize) -> StepBy<Self>
where\n Self: Sized,

Creates an iterator starting at the same point, but stepping by\nthe given amount at each iteration. Read more
1.6.0 · source§

fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>
where\n Self: Sized,\n U: IntoIterator<Item = Self::Item>,

Takes two iterators and creates a new iterator over both in sequence. Read more
1.6.0 · source§

fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>
where\n Self: Sized,\n U: IntoIterator,

‘Zips up’ two iterators into a single iterator of pairs. Read more
source§

fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
where\n Self: Sized,\n G: FnMut() -> Self::Item,

🔬This is a nightly-only experimental API. (iter_intersperse)
Creates a new iterator which places an item generated by separator\nbetween adjacent items of the original iterator. Read more
1.6.0 · source§

fn map<B, F>(self, f: F) -> Map<Self, F>
where\n Self: Sized,\n F: FnMut(Self::Item) -> B,

Takes a closure and creates an iterator which calls that closure on each\nelement. Read more
1.21.0 · source§

fn for_each<F>(self, f: F)
where\n Self: Sized,\n F: FnMut(Self::Item),

Calls a closure on each element of an iterator. Read more
1.6.0 · source§

fn filter<P>(self, predicate: P) -> Filter<Self, P>
where\n Self: Sized,\n P: FnMut(&Self::Item) -> bool,

Creates an iterator which uses a closure to determine if an element\nshould be yielded. Read more
1.6.0 · source§

fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
where\n Self: Sized,\n F: FnMut(Self::Item) -> Option<B>,

Creates an iterator that both filters and maps. Read more
1.6.0 · source§

fn enumerate(self) -> Enumerate<Self>
where\n Self: Sized,

Creates an iterator which gives the current iteration count as well as\nthe next value. Read more
1.6.0 · source§

fn peekable(self) -> Peekable<Self>
where\n Self: Sized,

Creates an iterator which can use the peek and peek_mut methods\nto look at the next element of the iterator without consuming it. See\ntheir documentation for more information. Read more
1.6.0 · source§

fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
where\n Self: Sized,\n P: FnMut(&Self::Item) -> bool,

Creates an iterator that skips elements based on a predicate. Read more
1.6.0 · source§

fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
where\n Self: Sized,\n P: FnMut(&Self::Item) -> bool,

Creates an iterator that yields elements based on a predicate. Read more
1.57.0 · source§

fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
where\n Self: Sized,\n P: FnMut(Self::Item) -> Option<B>,

Creates an iterator that both yields elements based on a predicate and maps. Read more
1.6.0 · source§

fn skip(self, n: usize) -> Skip<Self>
where\n Self: Sized,

Creates an iterator that skips the first n elements. Read more
1.6.0 · source§

fn take(self, n: usize) -> Take<Self>
where\n Self: Sized,

Creates an iterator that yields the first n elements, or fewer\nif the underlying iterator ends sooner. Read more
1.6.0 · source§

fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
where\n Self: Sized,\n F: FnMut(&mut St, Self::Item) -> Option<B>,

An iterator adapter which, like fold, holds internal state, but\nunlike fold, produces a new iterator. Read more
1.6.0 · source§

fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
where\n Self: Sized,\n U: IntoIterator,\n F: FnMut(Self::Item) -> U,

Creates an iterator that works like map, but flattens nested structure. Read more
source§

fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
where\n Self: Sized,\n F: FnMut(&[Self::Item; N]) -> R,

🔬This is a nightly-only experimental API. (iter_map_windows)
Calls the given function f for each contiguous window of size N over\nself and returns an iterator over the outputs of f. Like slice::windows(),\nthe windows during mapping overlap as well. Read more
1.6.0 · source§

fn fuse(self) -> Fuse<Self>
where\n Self: Sized,

Creates an iterator which ends after the first None. Read more
1.6.0 · source§

fn inspect<F>(self, f: F) -> Inspect<Self, F>
where\n Self: Sized,\n F: FnMut(&Self::Item),

Does something with each element of an iterator, passing the value on. Read more
1.6.0 · source§

fn by_ref(&mut self) -> &mut Self
where\n Self: Sized,

Borrows an iterator, rather than consuming it. Read more
1.6.0 · source§

fn collect<B>(self) -> B
where\n B: FromIterator<Self::Item>,\n Self: Sized,

Transforms an iterator into a collection. Read more
source§

fn collect_into<E>(self, collection: &mut E) -> &mut E
where\n E: Extend<Self::Item>,\n Self: Sized,

🔬This is a nightly-only experimental API. (iter_collect_into)
Collects all the items from an iterator into a collection. Read more
1.6.0 · source§

fn partition<B, F>(self, f: F) -> (B, B)
where\n Self: Sized,\n B: Default + Extend<Self::Item>,\n F: FnMut(&Self::Item) -> bool,

Consumes an iterator, creating two collections from it. Read more
source§

fn is_partitioned<P>(self, predicate: P) -> bool
where\n Self: Sized,\n P: FnMut(Self::Item) -> bool,

🔬This is a nightly-only experimental API. (iter_is_partitioned)
Checks if the elements of this iterator are partitioned according to the given predicate,\nsuch that all those that return true precede all those that return false. Read more
1.27.0 · source§

fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where\n Self: Sized,\n F: FnMut(B, Self::Item) -> R,\n R: Try<Output = B>,

An iterator method that applies a function as long as it returns\nsuccessfully, producing a single, final value. Read more
1.27.0 · source§

fn try_for_each<F, R>(&mut self, f: F) -> R
where\n Self: Sized,\n F: FnMut(Self::Item) -> R,\n R: Try<Output = ()>,

An iterator method that applies a fallible function to each item in the\niterator, stopping at the first error and returning that error. Read more
1.6.0 · source§

fn fold<B, F>(self, init: B, f: F) -> B
where\n Self: Sized,\n F: FnMut(B, Self::Item) -> B,

Folds every element into an accumulator by applying an operation,\nreturning the final result. Read more
1.51.0 · source§

fn reduce<F>(self, f: F) -> Option<Self::Item>
where\n Self: Sized,\n F: FnMut(Self::Item, Self::Item) -> Self::Item,

Reduces the elements to a single one, by repeatedly applying a reducing\noperation. Read more
source§

fn try_reduce<R>(\n &mut self,\n f: impl FnMut(Self::Item, Self::Item) -> R,\n) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryType
where\n Self: Sized,\n R: Try<Output = Self::Item>,\n <R as Try>::Residual: Residual<Option<Self::Item>>,

🔬This is a nightly-only experimental API. (iterator_try_reduce)
Reduces the elements to a single one by repeatedly applying a reducing operation. If the\nclosure returns a failure, the failure is propagated back to the caller immediately. Read more
1.6.0 · source§

fn all<F>(&mut self, f: F) -> bool
where\n Self: Sized,\n F: FnMut(Self::Item) -> bool,

Tests if every element of the iterator matches a predicate. Read more
1.6.0 · source§

fn any<F>(&mut self, f: F) -> bool
where\n Self: Sized,\n F: FnMut(Self::Item) -> bool,

Tests if any element of the iterator matches a predicate. Read more
1.6.0 · source§

fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
where\n Self: Sized,\n P: FnMut(&Self::Item) -> bool,

Searches for an element of an iterator that satisfies a predicate. Read more
1.30.0 · source§

fn find_map<B, F>(&mut self, f: F) -> Option<B>
where\n Self: Sized,\n F: FnMut(Self::Item) -> Option<B>,

Applies function to the elements of iterator and returns\nthe first non-none result. Read more
source§

fn try_find<R>(\n &mut self,\n f: impl FnMut(&Self::Item) -> R,\n) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryType
where\n Self: Sized,\n R: Try<Output = bool>,\n <R as Try>::Residual: Residual<Option<Self::Item>>,

🔬This is a nightly-only experimental API. (try_find)
Applies function to the elements of iterator and returns\nthe first true result or the first error. Read more
1.6.0 · source§

fn position<P>(&mut self, predicate: P) -> Option<usize>
where\n Self: Sized,\n P: FnMut(Self::Item) -> bool,

Searches for an element in an iterator, returning its index. Read more
1.6.0 · source§

fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>
where\n B: Ord,\n Self: Sized,\n F: FnMut(&Self::Item) -> B,

Returns the element that gives the maximum value from the\nspecified function. Read more
1.15.0 · source§

fn max_by<F>(self, compare: F) -> Option<Self::Item>
where\n Self: Sized,\n F: FnMut(&Self::Item, &Self::Item) -> Ordering,

Returns the element that gives the maximum value with respect to the\nspecified comparison function. Read more
1.6.0 · source§

fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>
where\n B: Ord,\n Self: Sized,\n F: FnMut(&Self::Item) -> B,

Returns the element that gives the minimum value from the\nspecified function. Read more
1.15.0 · source§

fn min_by<F>(self, compare: F) -> Option<Self::Item>
where\n Self: Sized,\n F: FnMut(&Self::Item, &Self::Item) -> Ordering,

Returns the element that gives the minimum value with respect to the\nspecified comparison function. Read more
1.6.0 · source§

fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
where\n FromA: Default + Extend<A>,\n FromB: Default + Extend<B>,\n Self: Sized + Iterator<Item = (A, B)>,

Converts an iterator of pairs into a pair of containers. Read more
1.36.0 · source§

fn copied<'a, T>(self) -> Copied<Self>
where\n T: 'a + Copy,\n Self: Sized + Iterator<Item = &'a T>,

Creates an iterator which copies all of its elements. Read more
1.6.0 · source§

fn cloned<'a, T>(self) -> Cloned<Self>
where\n T: 'a + Clone,\n Self: Sized + Iterator<Item = &'a T>,

Creates an iterator which clones all of its elements. Read more
source§

fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>
where\n Self: Sized,

🔬This is a nightly-only experimental API. (iter_array_chunks)
Returns an iterator over N elements of the iterator at a time. Read more
1.11.0 · source§

fn sum<S>(self) -> S
where\n Self: Sized,\n S: Sum<Self::Item>,

Sums the elements of an iterator. Read more
1.11.0 · source§

fn product<P>(self) -> P
where\n Self: Sized,\n P: Product<Self::Item>,

Iterates over the entire iterator, multiplying all the elements Read more
source§

fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
where\n Self: Sized,\n I: IntoIterator,\n F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering,

🔬This is a nightly-only experimental API. (iter_order_by)
Lexicographically compares the elements of this Iterator with those\nof another with respect to the specified comparison function. Read more
1.6.0 · source§

fn partial_cmp<I>(self, other: I) -> Option<Ordering>
where\n I: IntoIterator,\n Self::Item: PartialOrd<<I as IntoIterator>::Item>,\n Self: Sized,

Lexicographically compares the PartialOrd elements of\nthis Iterator with those of another. The comparison works like short-circuit\nevaluation, returning a result without comparing the remaining elements.\nAs soon as an order can be determined, the evaluation stops and a result is returned. Read more
source§

fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>
where\n Self: Sized,\n I: IntoIterator,\n F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,

🔬This is a nightly-only experimental API. (iter_order_by)
Lexicographically compares the elements of this Iterator with those\nof another with respect to the specified comparison function. Read more
1.6.0 · source§

fn eq<I>(self, other: I) -> bool
where\n I: IntoIterator,\n Self::Item: PartialEq<<I as IntoIterator>::Item>,\n Self: Sized,

Determines if the elements of this Iterator are equal to those of\nanother. Read more
source§

fn eq_by<I, F>(self, other: I, eq: F) -> bool
where\n Self: Sized,\n I: IntoIterator,\n F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool,

🔬This is a nightly-only experimental API. (iter_order_by)
Determines if the elements of this Iterator are equal to those of\nanother with respect to the specified equality function. Read more
1.6.0 · source§

fn ne<I>(self, other: I) -> bool
where\n I: IntoIterator,\n Self::Item: PartialEq<<I as IntoIterator>::Item>,\n Self: Sized,

Determines if the elements of this Iterator are not equal to those of\nanother. Read more
1.6.0 · source§

fn lt<I>(self, other: I) -> bool
where\n I: IntoIterator,\n Self::Item: PartialOrd<<I as IntoIterator>::Item>,\n Self: Sized,

Determines if the elements of this Iterator are lexicographically\nless than those of another. Read more
1.6.0 · source§

fn le<I>(self, other: I) -> bool
where\n I: IntoIterator,\n Self::Item: PartialOrd<<I as IntoIterator>::Item>,\n Self: Sized,

Determines if the elements of this Iterator are lexicographically\nless or equal to those of another. Read more
1.6.0 · source§

fn gt<I>(self, other: I) -> bool
where\n I: IntoIterator,\n Self::Item: PartialOrd<<I as IntoIterator>::Item>,\n Self: Sized,

Determines if the elements of this Iterator are lexicographically\ngreater than those of another. Read more
1.6.0 · source§

fn ge<I>(self, other: I) -> bool
where\n I: IntoIterator,\n Self::Item: PartialOrd<<I as IntoIterator>::Item>,\n Self: Sized,

Determines if the elements of this Iterator are lexicographically\ngreater than or equal to those of another. Read more
1.82.0 · source§

fn is_sorted_by<F>(self, compare: F) -> bool
where\n Self: Sized,\n F: FnMut(&Self::Item, &Self::Item) -> bool,

Checks if the elements of this iterator are sorted using the given comparator function. Read more
1.82.0 · source§

fn is_sorted_by_key<F, K>(self, f: F) -> bool
where\n Self: Sized,\n F: FnMut(Self::Item) -> K,\n K: PartialOrd,

Checks if the elements of this iterator are sorted using the given key extraction\nfunction. Read more
","Iterator","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Ord for Box<T, A>
where\n T: Ord + ?Sized,\n A: Allocator,

source§

fn cmp(&self, other: &Box<T, A>) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where\n Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where\n Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where\n Self: Sized,

Restrict a value to a certain interval. Read more
","Ord","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> PartialEq for Box<T, A>
where\n T: PartialEq + ?Sized,\n A: Allocator,

source§

fn eq(&self, other: &Box<T, A>) -> bool

Tests for self and other values to be equal, and is used by ==.
source§

fn ne(&self, other: &Box<T, A>) -> bool

Tests for !=. The default implementation is almost always sufficient,\nand should not be overridden without very good reason.
","PartialEq","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> PartialOrd for Box<T, A>
where\n T: PartialOrd + ?Sized,\n A: Allocator,

source§

fn partial_cmp(&self, other: &Box<T, A>) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
source§

fn lt(&self, other: &Box<T, A>) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
source§

fn le(&self, other: &Box<T, A>) -> bool

Tests less than or equal to (for self and other) and is used by the\n<= operator. Read more
source§

fn ge(&self, other: &Box<T, A>) -> bool

Tests greater than or equal to (for self and other) and is used by\nthe >= operator. Read more
source§

fn gt(&self, other: &Box<T, A>) -> bool

Tests greater than (for self and other) and is used by the >\noperator. Read more
","PartialOrd","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Pointer for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Pointer","actix_service::boxed::BoxService"],["
1.0.0 · source§

impl<R> Read for Box<R>
where\n R: Read + ?Sized,

source§

fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>

Pull some bytes from this source into the specified buffer, returning\nhow many bytes were read. Read more
source§

fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>

🔬This is a nightly-only experimental API. (read_buf)
Pull some bytes from this source into the specified buffer. Read more
source§

fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>

Like read, except that it reads into a slice of buffers. Read more
source§

fn is_read_vectored(&self) -> bool

🔬This is a nightly-only experimental API. (can_vector)
Determines if this Reader has an efficient read_vectored\nimplementation. Read more
source§

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>

Reads all bytes until EOF in this source, placing them into buf. Read more
source§

fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>

Reads all bytes until EOF in this source, appending them to buf. Read more
source§

fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>

Reads the exact number of bytes required to fill buf. Read more
source§

fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>

🔬This is a nightly-only experimental API. (read_buf)
Reads the exact number of bytes required to fill cursor. Read more
1.0.0 · source§

fn by_ref(&mut self) -> &mut Self
where\n Self: Sized,

Creates a “by reference” adaptor for this instance of Read. Read more
1.0.0 · source§

fn bytes(self) -> Bytes<Self>
where\n Self: Sized,

Transforms this Read instance to an Iterator over its bytes. Read more
1.0.0 · source§

fn chain<R>(self, next: R) -> Chain<Self, R>
where\n R: Read,\n Self: Sized,

Creates an adapter which will chain this stream with another. Read more
1.0.0 · source§

fn take(self, limit: u64) -> Take<Self>
where\n Self: Sized,

Creates an adapter which will read at most limit bytes from it. Read more
","Read","actix_service::boxed::BoxService"],["
1.0.0 · source§

impl<S> Seek for Box<S>
where\n S: Seek + ?Sized,

source§

fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error>

Seek to an offset, in bytes, in a stream. Read more
source§

fn stream_position(&mut self) -> Result<u64, Error>

Returns the current seek position from the start of the stream. Read more
1.55.0 · source§

fn rewind(&mut self) -> Result<(), Error>

Rewind to the beginning of a stream. Read more
source§

fn stream_len(&mut self) -> Result<u64, Error>

🔬This is a nightly-only experimental API. (seek_stream_len)
Returns the length of this stream (in bytes). Read more
1.80.0 · source§

fn seek_relative(&mut self, offset: i64) -> Result<(), Error>

Seeks relative to the current position. Read more
","Seek","actix_service::boxed::BoxService"],["
source§

impl<S, Req> Service<Req> for Box<S>
where\n S: Service<Req> + ?Sized,

source§

type Response = <S as Service<Req>>::Response

Responses given by the service.
source§

type Error = <S as Service<Req>>::Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = <S as Service<Req>>::Future

The future response value.
source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), S::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, request: Req) -> S::Future

Process the request and return the response asynchronously. Read more
","Service","actix_service::boxed::BoxService"],["
§

impl<S> Stream for Box<S>
where\n S: Stream + Unpin + ?Sized,

§

type Item = <S as Stream>::Item

Values yielded by the stream.
§

fn poll_next(\n self: Pin<&mut Box<S>>,\n cx: &mut Context<'_>,\n) -> Poll<Option<<Box<S> as Stream>::Item>>

Attempt to pull out the next value of this stream, registering the\ncurrent task for wakeup if the value is not yet available, and returning\nNone if the stream is exhausted. Read more
§

fn size_hint(&self) -> (usize, Option<usize>)

Returns the bounds on the remaining length of the stream. Read more
","Stream","actix_service::boxed::BoxService"],["
1.0.0 · source§

impl<W> Write for Box<W>
where\n W: Write + ?Sized,

source§

fn write(&mut self, buf: &[u8]) -> Result<usize, Error>

Writes a buffer into this writer, returning how many bytes were written. Read more
source§

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize, Error>

Like write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

🔬This is a nightly-only experimental API. (can_vector)
Determines if this Writer has an efficient write_vectored\nimplementation. Read more
source§

fn flush(&mut self) -> Result<(), Error>

Flushes this output stream, ensuring that all intermediately buffered\ncontents reach their destination. Read more
source§

fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>

Attempts to write an entire buffer into this writer. Read more
source§

fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<(), Error>

Writes a formatted string into this writer, returning any error\nencountered. Read more
source§

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>

🔬This is a nightly-only experimental API. (write_all_vectored)
Attempts to write multiple buffers into this writer. Read more
1.0.0 · source§

fn by_ref(&mut self) -> &mut Self
where\n Self: Sized,

Creates a “by reference” adapter for this instance of Write. Read more
","Write","actix_service::boxed::BoxService"],["
source§

impl<T, U, A> CoerceUnsized<Box<U, A>> for Box<T, A>
where\n T: Unsize<U> + ?Sized,\n A: Allocator,\n U: ?Sized,

","CoerceUnsized>","actix_service::boxed::BoxService"],["
source§

impl<T, A> DerefPure for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

","DerefPure","actix_service::boxed::BoxService"],["
source§

impl<T, U> DispatchFromDyn<Box<U>> for Box<T>
where\n T: Unsize<U> + ?Sized,\n U: ?Sized,

","DispatchFromDyn>","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Eq for Box<T, A>
where\n T: Eq + ?Sized,\n A: Allocator,

","Eq","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<I, A> FusedIterator for Box<I, A>
where\n I: FusedIterator + ?Sized,\n A: Allocator,

","FusedIterator","actix_service::boxed::BoxService"],["
source§

impl<T, A> PinCoerceUnsized for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

","PinCoerceUnsized","actix_service::boxed::BoxService"],["
1.36.0 · source§

impl<T, A> Unpin for Box<T, A>
where\n A: Allocator,\n T: ?Sized,

","Unpin","actix_service::boxed::BoxService"]]]]); + if (window.register_type_impls) { + window.register_type_impls(type_impls); + } else { + window.pending_type_impls = type_impls; + } +})() +//{"start":55,"fragment_lengths":[386806]} \ No newline at end of file diff --git a/type.impl/alloc/rc/struct.Rc.js b/type.impl/alloc/rc/struct.Rc.js new file mode 100644 index 00000000..7a0c8440 --- /dev/null +++ b/type.impl/alloc/rc/struct.Rc.js @@ -0,0 +1,9 @@ +(function() { + var type_impls = Object.fromEntries([["actix_service",[["
1.69.0 · source§

impl<T> AsFd for Rc<T>
where\n T: AsFd + ?Sized,

source§

fn as_fd(&self) -> BorrowedFd<'_>

Borrows the file descriptor. Read more
","AsFd","actix_service::boxed::RcService"],["
1.69.0 · source§

impl<T> AsRawFd for Rc<T>
where\n T: AsRawFd,

source§

fn as_raw_fd(&self) -> i32

Extracts the raw file descriptor. Read more
","AsRawFd","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> AsRef<T> for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn as_ref(&self) -> &T

Converts this type into a shared reference of the (usually inferred) input type.
","AsRef","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Borrow<T> for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
","Borrow","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Clone for Rc<T, A>
where\n A: Allocator + Clone,\n T: ?Sized,

source§

fn clone(&self) -> Rc<T, A>

Makes a clone of the Rc pointer.

\n

This creates another pointer to the same allocation, increasing the\nstrong reference count.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nlet _ = Rc::clone(&five);
\n
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
","Clone","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Debug for Rc<T, A>
where\n T: Debug + ?Sized,\n A: Allocator,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Debug","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T> Default for Rc<T>
where\n T: Default,

source§

fn default() -> Rc<T>

Creates a new Rc<T>, with the Default value for T.

\n
§Examples
\n
use std::rc::Rc;\n\nlet x: Rc<i32> = Default::default();\nassert_eq!(*x, 0);
\n
","Default","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Deref for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

type Target = T

The resulting type after dereferencing.
source§

fn deref(&self) -> &T

Dereferences the value.
","Deref","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Display for Rc<T, A>
where\n T: Display + ?Sized,\n A: Allocator,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Display","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Drop for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn drop(&mut self)

Drops the Rc.

\n

This will decrement the strong reference count. If the strong reference\ncount reaches zero then the only other references (if any) are\nWeak, so we drop the inner value.

\n
§Examples
\n
use std::rc::Rc;\n\nstruct Foo;\n\nimpl Drop for Foo {\n    fn drop(&mut self) {\n        println!(\"dropped!\");\n    }\n}\n\nlet foo  = Rc::new(Foo);\nlet foo2 = Rc::clone(&foo);\n\ndrop(foo);    // Doesn't print anything\ndrop(foo2);   // Prints \"dropped!\"
\n
","Drop","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> From<Box<T, A>> for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn from(v: Box<T, A>) -> Rc<T, A>

Move a boxed object to a new, reference counted, allocation.

\n
§Example
\n
let original: Box<i32> = Box::new(1);\nlet shared: Rc<i32> = Rc::from(original);\nassert_eq!(1, *shared);
\n
","From>","actix_service::boxed::RcService"],["
1.45.0 · source§

impl<'a, B> From<Cow<'a, B>> for Rc<B>
where\n B: ToOwned + ?Sized,\n Rc<B>: From<&'a B> + From<<B as ToOwned>::Owned>,

source§

fn from(cow: Cow<'a, B>) -> Rc<B>

Creates a reference-counted pointer from a clone-on-write pointer by\ncopying its content.

\n
§Example
\n
let cow: Cow<'_, str> = Cow::Borrowed(\"eggplant\");\nlet shared: Rc<str> = Rc::from(cow);\nassert_eq!(\"eggplant\", &shared[..]);
\n
","From>","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T> From<T> for Rc<T>

source§

fn from(t: T) -> Rc<T>

Converts a generic type T into an Rc<T>

\n

The conversion allocates on the heap and moves t\nfrom the stack into it.

\n
§Example
\n
let x = 5;\nlet rc = Rc::new(5);\n\nassert_eq!(Rc::from(x), rc);
\n
","From","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Hash for Rc<T, A>
where\n T: Hash + ?Sized,\n A: Allocator,

source§

fn hash<H>(&self, state: &mut H)
where\n H: Hasher,

Feeds this value into the given Hasher. Read more
1.6.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where\n H: Hasher,\n Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
","Hash","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Ord for Rc<T, A>
where\n T: Ord + ?Sized,\n A: Allocator,

source§

fn cmp(&self, other: &Rc<T, A>) -> Ordering

Comparison for two Rcs.

\n

The two are compared by calling cmp() on their inner values.

\n
§Examples
\n
use std::rc::Rc;\nuse std::cmp::Ordering;\n\nlet five = Rc::new(5);\n\nassert_eq!(Ordering::Less, five.cmp(&Rc::new(6)));
\n
1.21.0 · source§

fn max(self, other: Self) -> Self
where\n Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where\n Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where\n Self: Sized,

Restrict a value to a certain interval. Read more
","Ord","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> PartialEq for Rc<T, A>
where\n T: PartialEq + ?Sized,\n A: Allocator,

source§

fn eq(&self, other: &Rc<T, A>) -> bool

Equality for two Rcs.

\n

Two Rcs are equal if their inner values are equal, even if they are\nstored in different allocation.

\n

If T also implements Eq (implying reflexivity of equality),\ntwo Rcs that point to the same allocation are\nalways equal.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nassert!(five == Rc::new(5));
\n
source§

fn ne(&self, other: &Rc<T, A>) -> bool

Inequality for two Rcs.

\n

Two Rcs are not equal if their inner values are not equal.

\n

If T also implements Eq (implying reflexivity of equality),\ntwo Rcs that point to the same allocation are\nalways equal.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nassert!(five != Rc::new(6));
\n
","PartialEq","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> PartialOrd for Rc<T, A>
where\n T: PartialOrd + ?Sized,\n A: Allocator,

source§

fn partial_cmp(&self, other: &Rc<T, A>) -> Option<Ordering>

Partial comparison for two Rcs.

\n

The two are compared by calling partial_cmp() on their inner values.

\n
§Examples
\n
use std::rc::Rc;\nuse std::cmp::Ordering;\n\nlet five = Rc::new(5);\n\nassert_eq!(Some(Ordering::Less), five.partial_cmp(&Rc::new(6)));
\n
source§

fn lt(&self, other: &Rc<T, A>) -> bool

Less-than comparison for two Rcs.

\n

The two are compared by calling < on their inner values.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nassert!(five < Rc::new(6));
\n
source§

fn le(&self, other: &Rc<T, A>) -> bool

‘Less than or equal to’ comparison for two Rcs.

\n

The two are compared by calling <= on their inner values.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nassert!(five <= Rc::new(5));
\n
source§

fn gt(&self, other: &Rc<T, A>) -> bool

Greater-than comparison for two Rcs.

\n

The two are compared by calling > on their inner values.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nassert!(five > Rc::new(4));
\n
source§

fn ge(&self, other: &Rc<T, A>) -> bool

‘Greater than or equal to’ comparison for two Rcs.

\n

The two are compared by calling >= on their inner values.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nassert!(five >= Rc::new(5));
\n
","PartialOrd","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Pointer for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Pointer","actix_service::boxed::RcService"],["
source§

impl<T> Rc<T>
where\n T: ?Sized,

1.36.0 · source

pub unsafe fn from_raw(ptr: *const T) -> Rc<T>

Constructs an Rc<T> from a raw pointer.

\n

The raw pointer must have been previously returned by a call to\nRc<U>::into_raw with the following requirements:

\n
    \n
  • If U is sized, it must have the same size and alignment as T. This\nis trivially true if U is T.
  • \n
  • If U is unsized, its data pointer must have the same size and\nalignment as T. This is trivially true if Rc<U> was constructed\nthrough Rc<T> and then converted to Rc<U> through an unsized\ncoercion.
  • \n
\n

Note that if U or U’s data pointer is not T but has the same size\nand alignment, this is basically like transmuting references of\ndifferent types. See mem::transmute for more information\non what restrictions apply in this case.

\n

The raw pointer must point to a block of memory allocated by the global allocator

\n

The user of from_raw has to make sure a specific value of T is only\ndropped once.

\n

This function is unsafe because improper use may lead to memory unsafety,\neven if the returned Rc<T> is never accessed.

\n
§Examples
\n
use std::rc::Rc;\n\nlet x = Rc::new(\"hello\".to_owned());\nlet x_ptr = Rc::into_raw(x);\n\nunsafe {\n    // Convert back to an `Rc` to prevent leak.\n    let x = Rc::from_raw(x_ptr);\n    assert_eq!(&*x, \"hello\");\n\n    // Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe.\n}\n\n// The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!
\n

Convert a slice back into its original array:

\n\n
use std::rc::Rc;\n\nlet x: Rc<[u32]> = Rc::new([1, 2, 3]);\nlet x_ptr: *const [u32] = Rc::into_raw(x);\n\nunsafe {\n    let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>());\n    assert_eq!(&*x, &[1, 2, 3]);\n}
\n
1.53.0 · source

pub unsafe fn increment_strong_count(ptr: *const T)

Increments the strong reference count on the Rc<T> associated with the\nprovided pointer by one.

\n
§Safety
\n

The pointer must have been obtained through Rc::into_raw, the\nassociated Rc instance must be valid (i.e. the strong count must be at\nleast 1) for the duration of this method, and ptr must point to a block of memory\nallocated by the global allocator.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nunsafe {\n    let ptr = Rc::into_raw(five);\n    Rc::increment_strong_count(ptr);\n\n    let five = Rc::from_raw(ptr);\n    assert_eq!(2, Rc::strong_count(&five));\n}
\n
1.53.0 · source

pub unsafe fn decrement_strong_count(ptr: *const T)

Decrements the strong reference count on the Rc<T> associated with the\nprovided pointer by one.

\n
§Safety
\n

The pointer must have been obtained through Rc::into_raw, the\nassociated Rc instance must be valid (i.e. the strong count must be at\nleast 1) when invoking this method, and ptr must point to a block of memory\nallocated by the global allocator. This method can be used to release the final Rc and\nbacking storage, but should not be called after the final Rc has been released.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nunsafe {\n    let ptr = Rc::into_raw(five);\n    Rc::increment_strong_count(ptr);\n\n    let five = Rc::from_raw(ptr);\n    assert_eq!(2, Rc::strong_count(&five));\n    Rc::decrement_strong_count(ptr);\n    assert_eq!(1, Rc::strong_count(&five));\n}
\n
",0,"actix_service::boxed::RcService"],["
source§

impl<T> Rc<T>

1.36.0 · source

pub fn new(value: T) -> Rc<T>

Constructs a new Rc<T>.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);
\n
1.60.0 · source

pub fn new_cyclic<F>(data_fn: F) -> Rc<T>
where\n F: FnOnce(&Weak<T>) -> T,

Constructs a new Rc<T> while giving you a Weak<T> to the allocation,\nto allow you to construct a T which holds a weak pointer to itself.

\n

Generally, a structure circularly referencing itself, either directly or\nindirectly, should not hold a strong reference to itself to prevent a memory leak.\nUsing this function, you get access to the weak pointer during the\ninitialization of T, before the Rc<T> is created, such that you can\nclone and store it inside the T.

\n

new_cyclic first allocates the managed allocation for the Rc<T>,\nthen calls your closure, giving it a Weak<T> to this allocation,\nand only afterwards completes the construction of the Rc<T> by placing\nthe T returned from your closure into the allocation.

\n

Since the new Rc<T> is not fully-constructed until Rc<T>::new_cyclic\nreturns, calling upgrade on the weak reference inside your closure will\nfail and result in a None value.

\n
§Panics
\n

If data_fn panics, the panic is propagated to the caller, and the\ntemporary Weak<T> is dropped normally.

\n
§Examples
\n
use std::rc::{Rc, Weak};\n\nstruct Gadget {\n    me: Weak<Gadget>,\n}\n\nimpl Gadget {\n    /// Constructs a reference counted Gadget.\n    fn new() -> Rc<Self> {\n        // `me` is a `Weak<Gadget>` pointing at the new allocation of the\n        // `Rc` we're constructing.\n        Rc::new_cyclic(|me| {\n            // Create the actual struct here.\n            Gadget { me: me.clone() }\n        })\n    }\n\n    /// Returns a reference counted pointer to Self.\n    fn me(&self) -> Rc<Self> {\n        self.me.upgrade().unwrap()\n    }\n}
\n
1.82.0 · source

pub fn new_uninit() -> Rc<MaybeUninit<T>>

Constructs a new Rc with uninitialized contents.

\n
§Examples
\n
#![feature(get_mut_unchecked)]\n\nuse std::rc::Rc;\n\nlet mut five = Rc::<u32>::new_uninit();\n\n// Deferred initialization:\nRc::get_mut(&mut five).unwrap().write(5);\n\nlet five = unsafe { five.assume_init() };\n\nassert_eq!(*five, 5)
\n
source

pub fn new_zeroed() -> Rc<MaybeUninit<T>>

🔬This is a nightly-only experimental API. (new_zeroed_alloc)

Constructs a new Rc with uninitialized contents, with the memory\nbeing filled with 0 bytes.

\n

See MaybeUninit::zeroed for examples of correct and\nincorrect usage of this method.

\n
§Examples
\n
#![feature(new_zeroed_alloc)]\n\nuse std::rc::Rc;\n\nlet zero = Rc::<u32>::new_zeroed();\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0)
\n
source

pub fn try_new(value: T) -> Result<Rc<T>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc<T>, returning an error if the allocation fails

\n
§Examples
\n
#![feature(allocator_api)]\nuse std::rc::Rc;\n\nlet five = Rc::try_new(5);
\n
source

pub fn try_new_uninit() -> Result<Rc<MaybeUninit<T>>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc with uninitialized contents, returning an error if the allocation fails

\n
§Examples
\n
#![feature(allocator_api)]\n#![feature(get_mut_unchecked)]\n\nuse std::rc::Rc;\n\nlet mut five = Rc::<u32>::try_new_uninit()?;\n\n// Deferred initialization:\nRc::get_mut(&mut five).unwrap().write(5);\n\nlet five = unsafe { five.assume_init() };\n\nassert_eq!(*five, 5);
\n
source

pub fn try_new_zeroed() -> Result<Rc<MaybeUninit<T>>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc with uninitialized contents, with the memory\nbeing filled with 0 bytes, returning an error if the allocation fails

\n

See MaybeUninit::zeroed for examples of correct and\nincorrect usage of this method.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::rc::Rc;\n\nlet zero = Rc::<u32>::try_new_zeroed()?;\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0);
\n
1.36.0 · source

pub fn pin(value: T) -> Pin<Rc<T>>

Constructs a new Pin<Rc<T>>. If T does not implement Unpin, then\nvalue will be pinned in memory and unable to be moved.

\n
",0,"actix_service::boxed::RcService"],["
source§

impl<T, A> Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

source

pub fn allocator(this: &Rc<T, A>) -> &A

🔬This is a nightly-only experimental API. (allocator_api)

Returns a reference to the underlying allocator.

\n

Note: this is an associated function, which means that you have\nto call it as Rc::allocator(&r) instead of r.allocator(). This\nis so that there is no conflict with a method on the inner type.

\n
1.36.0 · source

pub fn into_raw(this: Rc<T, A>) -> *const T

Consumes the Rc, returning the wrapped pointer.

\n

To avoid a memory leak the pointer must be converted back to an Rc using\nRc::from_raw.

\n
§Examples
\n
use std::rc::Rc;\n\nlet x = Rc::new(\"hello\".to_owned());\nlet x_ptr = Rc::into_raw(x);\nassert_eq!(unsafe { &*x_ptr }, \"hello\");
\n
source

pub fn into_raw_with_allocator(this: Rc<T, A>) -> (*const T, A)

🔬This is a nightly-only experimental API. (allocator_api)

Consumes the Rc, returning the wrapped pointer and allocator.

\n

To avoid a memory leak the pointer must be converted back to an Rc using\nRc::from_raw_in.

\n
§Examples
\n
#![feature(allocator_api)]\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet x = Rc::new_in(\"hello\".to_owned(), System);\nlet (ptr, alloc) = Rc::into_raw_with_allocator(x);\nassert_eq!(unsafe { &*ptr }, \"hello\");\nlet x = unsafe { Rc::from_raw_in(ptr, alloc) };\nassert_eq!(&*x, \"hello\");
\n
1.45.0 · source

pub fn as_ptr(this: &Rc<T, A>) -> *const T

Provides a raw pointer to the data.

\n

The counts are not affected in any way and the Rc is not consumed. The pointer is valid\nfor as long there are strong counts in the Rc.

\n
§Examples
\n
use std::rc::Rc;\n\nlet x = Rc::new(\"hello\".to_owned());\nlet y = Rc::clone(&x);\nlet x_ptr = Rc::as_ptr(&x);\nassert_eq!(x_ptr, Rc::as_ptr(&y));\nassert_eq!(unsafe { &*x_ptr }, \"hello\");
\n
source

pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Rc<T, A>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs an Rc<T, A> from a raw pointer in the provided allocator.

\n

The raw pointer must have been previously returned by a call to Rc<U, A>::into_raw with the following requirements:

\n
    \n
  • If U is sized, it must have the same size and alignment as T. This\nis trivially true if U is T.
  • \n
  • If U is unsized, its data pointer must have the same size and\nalignment as T. This is trivially true if Rc<U> was constructed\nthrough Rc<T> and then converted to Rc<U> through an unsized\ncoercion.
  • \n
\n

Note that if U or U’s data pointer is not T but has the same size\nand alignment, this is basically like transmuting references of\ndifferent types. See mem::transmute for more information\non what restrictions apply in this case.

\n

The raw pointer must point to a block of memory allocated by alloc

\n

The user of from_raw has to make sure a specific value of T is only\ndropped once.

\n

This function is unsafe because improper use may lead to memory unsafety,\neven if the returned Rc<T> is never accessed.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet x = Rc::new_in(\"hello\".to_owned(), System);\nlet x_ptr = Rc::into_raw(x);\n\nunsafe {\n    // Convert back to an `Rc` to prevent leak.\n    let x = Rc::from_raw_in(x_ptr, System);\n    assert_eq!(&*x, \"hello\");\n\n    // Further calls to `Rc::from_raw(x_ptr)` would be memory-unsafe.\n}\n\n// The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!
\n

Convert a slice back into its original array:

\n\n
#![feature(allocator_api)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet x: Rc<[u32], _> = Rc::new_in([1, 2, 3], System);\nlet x_ptr: *const [u32] = Rc::into_raw(x);\n\nunsafe {\n    let x: Rc<[u32; 3], _> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System);\n    assert_eq!(&*x, &[1, 2, 3]);\n}
\n
1.36.0 · source

pub fn downgrade(this: &Rc<T, A>) -> Weak<T, A>
where\n A: Clone,

Creates a new Weak pointer to this allocation.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\n\nlet weak_five = Rc::downgrade(&five);
\n
1.36.0 · source

pub fn weak_count(this: &Rc<T, A>) -> usize

Gets the number of Weak pointers to this allocation.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\nlet _weak_five = Rc::downgrade(&five);\n\nassert_eq!(1, Rc::weak_count(&five));
\n
1.36.0 · source

pub fn strong_count(this: &Rc<T, A>) -> usize

Gets the number of strong (Rc) pointers to this allocation.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\nlet _also_five = Rc::clone(&five);\n\nassert_eq!(2, Rc::strong_count(&five));
\n
source

pub unsafe fn increment_strong_count_in(ptr: *const T, alloc: A)
where\n A: Clone,

🔬This is a nightly-only experimental API. (allocator_api)

Increments the strong reference count on the Rc<T> associated with the\nprovided pointer by one.

\n
§Safety
\n

The pointer must have been obtained through Rc::into_raw, the\nassociated Rc instance must be valid (i.e. the strong count must be at\nleast 1) for the duration of this method, and ptr must point to a block of memory\nallocated by alloc

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet five = Rc::new_in(5, System);\n\nunsafe {\n    let ptr = Rc::into_raw(five);\n    Rc::increment_strong_count_in(ptr, System);\n\n    let five = Rc::from_raw_in(ptr, System);\n    assert_eq!(2, Rc::strong_count(&five));\n}
\n
source

pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A)

🔬This is a nightly-only experimental API. (allocator_api)

Decrements the strong reference count on the Rc<T> associated with the\nprovided pointer by one.

\n
§Safety
\n

The pointer must have been obtained through Rc::into_raw, the\nassociated Rc instance must be valid (i.e. the strong count must be at\nleast 1) when invoking this method, and ptr must point to a block of memory\nallocated by alloc. This method can be used to release the final Rc and backing storage,\nbut should not be called after the final Rc has been released.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet five = Rc::new_in(5, System);\n\nunsafe {\n    let ptr = Rc::into_raw(five);\n    Rc::increment_strong_count_in(ptr, System);\n\n    let five = Rc::from_raw_in(ptr, System);\n    assert_eq!(2, Rc::strong_count(&five));\n    Rc::decrement_strong_count_in(ptr, System);\n    assert_eq!(1, Rc::strong_count(&five));\n}
\n
1.36.0 · source

pub fn get_mut(this: &mut Rc<T, A>) -> Option<&mut T>

Returns a mutable reference into the given Rc, if there are\nno other Rc or Weak pointers to the same allocation.

\n

Returns None otherwise, because it is not safe to\nmutate a shared value.

\n

See also make_mut, which will clone\nthe inner value when there are other Rc pointers.

\n
§Examples
\n
use std::rc::Rc;\n\nlet mut x = Rc::new(3);\n*Rc::get_mut(&mut x).unwrap() = 4;\nassert_eq!(*x, 4);\n\nlet _y = Rc::clone(&x);\nassert!(Rc::get_mut(&mut x).is_none());
\n
source

pub unsafe fn get_mut_unchecked(this: &mut Rc<T, A>) -> &mut T

🔬This is a nightly-only experimental API. (get_mut_unchecked)

Returns a mutable reference into the given Rc,\nwithout any check.

\n

See also get_mut, which is safe and does appropriate checks.

\n
§Safety
\n

If any other Rc or Weak pointers to the same allocation exist, then\nthey must not be dereferenced or have active borrows for the duration\nof the returned borrow, and their inner type must be exactly the same as the\ninner type of this Rc (including lifetimes). This is trivially the case if no\nsuch pointers exist, for example immediately after Rc::new.

\n
§Examples
\n
#![feature(get_mut_unchecked)]\n\nuse std::rc::Rc;\n\nlet mut x = Rc::new(String::new());\nunsafe {\n    Rc::get_mut_unchecked(&mut x).push_str(\"foo\")\n}\nassert_eq!(*x, \"foo\");
\n

Other Rc pointers to the same allocation must be to the same type.

\n\n
#![feature(get_mut_unchecked)]\n\nuse std::rc::Rc;\n\nlet x: Rc<str> = Rc::from(\"Hello, world!\");\nlet mut y: Rc<[u8]> = x.clone().into();\nunsafe {\n    // this is Undefined Behavior, because x's inner type is str, not [u8]\n    Rc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8\n}\nprintln!(\"{}\", &*x); // Invalid UTF-8 in a str
\n

Other Rc pointers to the same allocation must be to the exact same type, including lifetimes.

\n\n
#![feature(get_mut_unchecked)]\n\nuse std::rc::Rc;\n\nlet x: Rc<&str> = Rc::new(\"Hello, world!\");\n{\n    let s = String::from(\"Oh, no!\");\n    let mut y: Rc<&str> = x.clone().into();\n    unsafe {\n        // this is Undefined Behavior, because x's inner type\n        // is &'long str, not &'short str\n        *Rc::get_mut_unchecked(&mut y) = &s;\n    }\n}\nprintln!(\"{}\", &*x); // Use-after-free
\n
1.36.0 · source

pub fn ptr_eq(this: &Rc<T, A>, other: &Rc<T, A>) -> bool

Returns true if the two Rcs point to the same allocation in a vein similar to\nptr::eq. This function ignores the metadata of dyn Trait pointers.

\n
§Examples
\n
use std::rc::Rc;\n\nlet five = Rc::new(5);\nlet same_five = Rc::clone(&five);\nlet other_five = Rc::new(5);\n\nassert!(Rc::ptr_eq(&five, &same_five));\nassert!(!Rc::ptr_eq(&five, &other_five));
\n
",0,"actix_service::boxed::RcService"],["
source§

impl<T, A> Rc<T, A>
where\n T: CloneToUninit + ?Sized,\n A: Allocator + Clone,

1.36.0 · source

pub fn make_mut(this: &mut Rc<T, A>) -> &mut T

Makes a mutable reference into the given Rc.

\n

If there are other Rc pointers to the same allocation, then make_mut will\nclone the inner value to a new allocation to ensure unique ownership. This is also\nreferred to as clone-on-write.

\n

However, if there are no other Rc pointers to this allocation, but some Weak\npointers, then the Weak pointers will be disassociated and the inner value will not\nbe cloned.

\n

See also get_mut, which will fail rather than cloning the inner value\nor disassociating Weak pointers.

\n
§Examples
\n
use std::rc::Rc;\n\nlet mut data = Rc::new(5);\n\n*Rc::make_mut(&mut data) += 1;         // Won't clone anything\nlet mut other_data = Rc::clone(&data); // Won't clone inner data\n*Rc::make_mut(&mut data) += 1;         // Clones inner data\n*Rc::make_mut(&mut data) += 1;         // Won't clone anything\n*Rc::make_mut(&mut other_data) *= 2;   // Won't clone anything\n\n// Now `data` and `other_data` point to different allocations.\nassert_eq!(*data, 8);\nassert_eq!(*other_data, 12);
\n

Weak pointers will be disassociated:

\n\n
use std::rc::Rc;\n\nlet mut data = Rc::new(75);\nlet weak = Rc::downgrade(&data);\n\nassert!(75 == *data);\nassert!(75 == *weak.upgrade().unwrap());\n\n*Rc::make_mut(&mut data) += 1;\n\nassert!(76 == *data);\nassert!(weak.upgrade().is_none());
\n
",0,"actix_service::boxed::RcService"],["
source§

impl<T, A> Rc<T, A>
where\n T: Clone,\n A: Allocator,

1.76.0 · source

pub fn unwrap_or_clone(this: Rc<T, A>) -> T

If we have the only reference to T then unwrap it. Otherwise, clone T and return the\nclone.

\n

Assuming rc_t is of type Rc<T>, this function is functionally equivalent to\n(*rc_t).clone(), but will avoid cloning the inner value where possible.

\n
§Examples
\n
let inner = String::from(\"test\");\nlet ptr = inner.as_ptr();\n\nlet rc = Rc::new(inner);\nlet inner = Rc::unwrap_or_clone(rc);\n// The inner value was not cloned\nassert!(ptr::eq(ptr, inner.as_ptr()));\n\nlet rc = Rc::new(inner);\nlet rc2 = rc.clone();\nlet inner = Rc::unwrap_or_clone(rc);\n// Because there were 2 references, we had to clone the inner value.\nassert!(!ptr::eq(ptr, inner.as_ptr()));\n// `rc2` is the last reference, so when we unwrap it we get back\n// the original `String`.\nlet inner = Rc::unwrap_or_clone(rc2);\nassert!(ptr::eq(ptr, inner.as_ptr()));
\n
",0,"actix_service::boxed::RcService"],["
source§

impl<T, A> Rc<T, A>
where\n A: Allocator,

source

pub fn new_in(value: T, alloc: A) -> Rc<T, A>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc in the provided allocator.

\n
§Examples
\n
#![feature(allocator_api)]\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet five = Rc::new_in(5, System);
\n
source

pub fn new_uninit_in(alloc: A) -> Rc<MaybeUninit<T>, A>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc with uninitialized contents in the provided allocator.

\n
§Examples
\n
#![feature(get_mut_unchecked)]\n#![feature(allocator_api)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet mut five = Rc::<u32, _>::new_uninit_in(System);\n\nlet five = unsafe {\n    // Deferred initialization:\n    Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);\n\n    five.assume_init()\n};\n\nassert_eq!(*five, 5)
\n
source

pub fn new_zeroed_in(alloc: A) -> Rc<MaybeUninit<T>, A>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc with uninitialized contents, with the memory\nbeing filled with 0 bytes, in the provided allocator.

\n

See MaybeUninit::zeroed for examples of correct and\nincorrect usage of this method.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet zero = Rc::<u32, _>::new_zeroed_in(System);\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0)
\n
source

pub fn new_cyclic_in<F>(data_fn: F, alloc: A) -> Rc<T, A>
where\n F: FnOnce(&Weak<T, A>) -> T,

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc<T, A> in the given allocator while giving you a Weak<T, A> to the allocation,\nto allow you to construct a T which holds a weak pointer to itself.

\n

Generally, a structure circularly referencing itself, either directly or\nindirectly, should not hold a strong reference to itself to prevent a memory leak.\nUsing this function, you get access to the weak pointer during the\ninitialization of T, before the Rc<T, A> is created, such that you can\nclone and store it inside the T.

\n

new_cyclic_in first allocates the managed allocation for the Rc<T, A>,\nthen calls your closure, giving it a Weak<T, A> to this allocation,\nand only afterwards completes the construction of the Rc<T, A> by placing\nthe T returned from your closure into the allocation.

\n

Since the new Rc<T, A> is not fully-constructed until Rc<T, A>::new_cyclic_in\nreturns, calling upgrade on the weak reference inside your closure will\nfail and result in a None value.

\n
§Panics
\n

If data_fn panics, the panic is propagated to the caller, and the\ntemporary Weak<T, A> is dropped normally.

\n
§Examples
\n

See new_cyclic.

\n
source

pub fn try_new_in(value: T, alloc: A) -> Result<Rc<T, A>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc<T> in the provided allocator, returning an error if the allocation\nfails

\n
§Examples
\n
#![feature(allocator_api)]\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet five = Rc::try_new_in(5, System);
\n
source

pub fn try_new_uninit_in(alloc: A) -> Result<Rc<MaybeUninit<T>, A>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc with uninitialized contents, in the provided allocator, returning an\nerror if the allocation fails

\n
§Examples
\n
#![feature(allocator_api)]\n#![feature(get_mut_unchecked)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet mut five = Rc::<u32, _>::try_new_uninit_in(System)?;\n\nlet five = unsafe {\n    // Deferred initialization:\n    Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);\n\n    five.assume_init()\n};\n\nassert_eq!(*five, 5);
\n
source

pub fn try_new_zeroed_in(alloc: A) -> Result<Rc<MaybeUninit<T>, A>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Rc with uninitialized contents, with the memory\nbeing filled with 0 bytes, in the provided allocator, returning an error if the allocation\nfails

\n

See MaybeUninit::zeroed for examples of correct and\nincorrect usage of this method.

\n
§Examples
\n
#![feature(allocator_api)]\n\nuse std::rc::Rc;\nuse std::alloc::System;\n\nlet zero = Rc::<u32, _>::try_new_zeroed_in(System)?;\nlet zero = unsafe { zero.assume_init() };\n\nassert_eq!(*zero, 0);
\n
source

pub fn pin_in(value: T, alloc: A) -> Pin<Rc<T, A>>
where\n A: 'static,

🔬This is a nightly-only experimental API. (allocator_api)

Constructs a new Pin<Rc<T>> in the provided allocator. If T does not implement Unpin, then\nvalue will be pinned in memory and unable to be moved.

\n
1.36.0 · source

pub fn try_unwrap(this: Rc<T, A>) -> Result<T, Rc<T, A>>

Returns the inner value, if the Rc has exactly one strong reference.

\n

Otherwise, an Err is returned with the same Rc that was\npassed in.

\n

This will succeed even if there are outstanding weak references.

\n
§Examples
\n
use std::rc::Rc;\n\nlet x = Rc::new(3);\nassert_eq!(Rc::try_unwrap(x), Ok(3));\n\nlet x = Rc::new(4);\nlet _y = Rc::clone(&x);\nassert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4);
\n
1.70.0 · source

pub fn into_inner(this: Rc<T, A>) -> Option<T>

Returns the inner value, if the Rc has exactly one strong reference.

\n

Otherwise, None is returned and the Rc is dropped.

\n

This will succeed even if there are outstanding weak references.

\n

If Rc::into_inner is called on every clone of this Rc,\nit is guaranteed that exactly one of the calls returns the inner value.\nThis means in particular that the inner value is not dropped.

\n

Rc::try_unwrap is conceptually similar to Rc::into_inner.\nAnd while they are meant for different use-cases, Rc::into_inner(this)\nis in fact equivalent to Rc::try_unwrap(this).ok().\n(Note that the same kind of equivalence does not hold true for\nArc, due to race conditions that do not apply to Rc!)

\n
§Examples
\n
use std::rc::Rc;\n\nlet x = Rc::new(3);\nassert_eq!(Rc::into_inner(x), Some(3));\n\nlet x = Rc::new(4);\nlet y = Rc::clone(&x);\n\nassert_eq!(Rc::into_inner(y), None);\nassert_eq!(Rc::into_inner(x), Some(4));
\n
",0,"actix_service::boxed::RcService"],["
source§

impl<S, Req> Service<Req> for Rc<S>
where\n S: Service<Req> + ?Sized,

source§

type Response = <S as Service<Req>>::Response

Responses given by the service.
source§

type Error = <S as Service<Req>>::Error

Errors produced by the service when polling readiness or executing call.
source§

type Future = <S as Service<Req>>::Future

The future response value.
source§

fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>

Returns Ready when the service is able to process requests. Read more
source§

fn call(&self, request: Req) -> S::Future

Process the request and return the response asynchronously. Read more
","Service","actix_service::boxed::RcService"],["
source§

impl<S, Req> ServiceFactory<Req> for Rc<S>
where\n S: ServiceFactory<Req>,

source§

type Response = <S as ServiceFactory<Req>>::Response

Responses given by the created services.
source§

type Error = <S as ServiceFactory<Req>>::Error

Errors produced by the created services.
source§

type Config = <S as ServiceFactory<Req>>::Config

Service factory configuration.
source§

type Service = <S as ServiceFactory<Req>>::Service

The kind of Service created by this factory.
source§

type InitError = <S as ServiceFactory<Req>>::InitError

Errors potentially raised while building a service.
source§

type Future = <S as ServiceFactory<Req>>::Future

The future of the Service instance.g
source§

fn new_service(&self, cfg: S::Config) -> S::Future

Create and return a new service asynchronously.
","ServiceFactory","actix_service::boxed::RcService"],["
source§

impl<T, S, Req> Transform<S, Req> for Rc<T>
where\n T: Transform<S, Req>,

source§

type Response = <T as Transform<S, Req>>::Response

Responses produced by the service.
source§

type Error = <T as Transform<S, Req>>::Error

Errors produced by the service.
source§

type Transform = <T as Transform<S, Req>>::Transform

The TransformService value created by this factory
source§

type InitError = <T as Transform<S, Req>>::InitError

Errors produced while building a transform service.
source§

type Future = <T as Transform<S, Req>>::Future

The future response value.
source§

fn new_transform(&self, service: S) -> T::Future

Creates and returns a new Transform component, asynchronously
","Transform","actix_service::boxed::RcService"],["
source§

impl<T, U, A> CoerceUnsized<Rc<U, A>> for Rc<T, A>
where\n T: Unsize<U> + ?Sized,\n A: Allocator,\n U: ?Sized,

","CoerceUnsized>","actix_service::boxed::RcService"],["
source§

impl<T, A> DerefPure for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

","DerefPure","actix_service::boxed::RcService"],["
source§

impl<T, U> DispatchFromDyn<Rc<U>> for Rc<T>
where\n T: Unsize<U> + ?Sized,\n U: ?Sized,

","DispatchFromDyn>","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Eq for Rc<T, A>
where\n T: Eq + ?Sized,\n A: Allocator,

","Eq","actix_service::boxed::RcService"],["
source§

impl<T, A> PinCoerceUnsized for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

","PinCoerceUnsized","actix_service::boxed::RcService"],["
1.58.0 · source§

impl<T, A> RefUnwindSafe for Rc<T, A>
where\n T: RefUnwindSafe + ?Sized,\n A: Allocator + UnwindSafe,

","RefUnwindSafe","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> !Send for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

","Send","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> !Sync for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

","Sync","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> Unpin for Rc<T, A>
where\n A: Allocator,\n T: ?Sized,

","Unpin","actix_service::boxed::RcService"],["
1.36.0 · source§

impl<T, A> UnwindSafe for Rc<T, A>
where\n T: RefUnwindSafe + ?Sized,\n A: Allocator + UnwindSafe,

","UnwindSafe","actix_service::boxed::RcService"]]]]); + if (window.register_type_impls) { + window.register_type_impls(type_impls); + } else { + window.pending_type_impls = type_impls; + } +})() +//{"start":55,"fragment_lengths":[171694]} \ No newline at end of file diff --git a/type.impl/core/pin/struct.Pin.js b/type.impl/core/pin/struct.Pin.js new file mode 100644 index 00000000..80e68a19 --- /dev/null +++ b/type.impl/core/pin/struct.Pin.js @@ -0,0 +1,9 @@ +(function() { + var type_impls = Object.fromEntries([["actix_service",[["
source§

impl<P> AsyncIterator for Pin<P>
where\n P: DerefMut,\n <P as Deref>::Target: AsyncIterator,

source§

type Item = <<P as Deref>::Target as AsyncIterator>::Item

🔬This is a nightly-only experimental API. (async_iterator)
The type of items yielded by the async iterator.
source§

fn poll_next(\n self: Pin<&mut Pin<P>>,\n cx: &mut Context<'_>,\n) -> Poll<Option<<Pin<P> as AsyncIterator>::Item>>

🔬This is a nightly-only experimental API. (async_iterator)
Attempts to pull out the next value of this async iterator, registering the\ncurrent task for wakeup if the value is not yet available, and returning\nNone if the async iterator is exhausted. Read more
source§

fn size_hint(&self) -> (usize, Option<usize>)

🔬This is a nightly-only experimental API. (async_iterator)
Returns the bounds on the remaining length of the async iterator. Read more
","AsyncIterator","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr> Clone for Pin<Ptr>
where\n Ptr: Clone,

source§

fn clone(&self) -> Pin<Ptr>

Returns a copy of the value. Read more
1.6.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
","Clone","actix_service::boxed::BoxFuture"],["
source§

impl<G, R, A> Coroutine<R> for Pin<Box<G, A>>
where\n G: Coroutine<R> + ?Sized,\n A: Allocator + 'static,

source§

type Yield = <G as Coroutine<R>>::Yield

🔬This is a nightly-only experimental API. (coroutine_trait)
The type of value this coroutine yields. Read more
source§

type Return = <G as Coroutine<R>>::Return

🔬This is a nightly-only experimental API. (coroutine_trait)
The type of value this coroutine returns. Read more
source§

fn resume(\n self: Pin<&mut Pin<Box<G, A>>>,\n arg: R,\n) -> CoroutineState<<Pin<Box<G, A>> as Coroutine<R>>::Yield, <Pin<Box<G, A>> as Coroutine<R>>::Return>

🔬This is a nightly-only experimental API. (coroutine_trait)
Resumes the execution of this coroutine. Read more
","Coroutine","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr> Debug for Pin<Ptr>
where\n Ptr: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Debug","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr> Deref for Pin<Ptr>
where\n Ptr: Deref,

source§

type Target = <Ptr as Deref>::Target

The resulting type after dereferencing.
source§

fn deref(&self) -> &<Ptr as Deref>::Target

Dereferences the value.
","Deref","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr> DerefMut for Pin<Ptr>
where\n Ptr: DerefMut,\n <Ptr as Deref>::Target: Unpin,

source§

fn deref_mut(&mut self) -> &mut <Ptr as Deref>::Target

Mutably dereferences the value.
","DerefMut","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr> Display for Pin<Ptr>
where\n Ptr: Display,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Display","actix_service::boxed::BoxFuture"],["
1.36.0 · source§

impl<T, A> From<Box<T, A>> for Pin<Box<T, A>>
where\n A: Allocator + 'static,\n T: ?Sized,

source§

fn from(boxed: Box<T, A>) -> Pin<Box<T, A>>

Converts a Box<T> into a Pin<Box<T>>. If T does not implement Unpin, then\n*boxed will be pinned in memory and unable to be moved.

\n

This conversion does not allocate on the heap and happens in place.

\n

This is also available via Box::into_pin.

\n

Constructing and pinning a Box with <Pin<Box<T>>>::from(Box::new(x))\ncan also be written more concisely using Box::pin(x).\nThis From implementation is useful if you already have a Box<T>, or you are\nconstructing a (pinned) Box in a different way than with Box::new.

\n
","From>","actix_service::boxed::BoxFuture"],["
§

impl<P> FusedFuture for Pin<P>
where\n P: DerefMut + Unpin,\n <P as Deref>::Target: FusedFuture,

§

fn is_terminated(&self) -> bool

Returns true if the underlying future should no longer be polled.
","FusedFuture","actix_service::boxed::BoxFuture"],["
§

impl<P> FusedStream for Pin<P>
where\n P: DerefMut + Unpin,\n <P as Deref>::Target: FusedStream,

§

fn is_terminated(&self) -> bool

Returns true if the stream should no longer be polled.
","FusedStream","actix_service::boxed::BoxFuture"],["
1.36.0 · source§

impl<P> Future for Pin<P>
where\n P: DerefMut,\n <P as Deref>::Target: Future,

source§

type Output = <<P as Deref>::Target as Future>::Output

The type of value produced on completion.
source§

fn poll(\n self: Pin<&mut Pin<P>>,\n cx: &mut Context<'_>,\n) -> Poll<<Pin<P> as Future>::Output>

Attempts to resolve the future to a final value, registering\nthe current task for wakeup if the value is not yet available. Read more
","Future","actix_service::boxed::BoxFuture"],["
1.41.0 · source§

impl<Ptr> Hash for Pin<Ptr>
where\n Ptr: Deref,\n <Ptr as Deref>::Target: Hash,

source§

fn hash<H>(&self, state: &mut H)
where\n H: Hasher,

Feeds this value into the given Hasher. Read more
1.6.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where\n H: Hasher,\n Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
","Hash","actix_service::boxed::BoxFuture"],["
1.41.0 · source§

impl<Ptr> Ord for Pin<Ptr>
where\n Ptr: Deref,\n <Ptr as Deref>::Target: Ord,

source§

fn cmp(&self, other: &Pin<Ptr>) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where\n Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where\n Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where\n Self: Sized,

Restrict a value to a certain interval. Read more
","Ord","actix_service::boxed::BoxFuture"],["
1.41.0 · source§

impl<Ptr, Q> PartialEq<Pin<Q>> for Pin<Ptr>
where\n Ptr: Deref,\n Q: Deref,\n <Ptr as Deref>::Target: PartialEq<<Q as Deref>::Target>,

source§

fn eq(&self, other: &Pin<Q>) -> bool

Tests for self and other values to be equal, and is used by ==.
source§

fn ne(&self, other: &Pin<Q>) -> bool

Tests for !=. The default implementation is almost always sufficient,\nand should not be overridden without very good reason.
","PartialEq>","actix_service::boxed::BoxFuture"],["
1.41.0 · source§

impl<Ptr, Q> PartialOrd<Pin<Q>> for Pin<Ptr>
where\n Ptr: Deref,\n Q: Deref,\n <Ptr as Deref>::Target: PartialOrd<<Q as Deref>::Target>,

source§

fn partial_cmp(&self, other: &Pin<Q>) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
source§

fn lt(&self, other: &Pin<Q>) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
source§

fn le(&self, other: &Pin<Q>) -> bool

Tests less than or equal to (for self and other) and is used by the\n<= operator. Read more
source§

fn gt(&self, other: &Pin<Q>) -> bool

Tests greater than (for self and other) and is used by the >\noperator. Read more
source§

fn ge(&self, other: &Pin<Q>) -> bool

Tests greater than or equal to (for self and other) and is used by\nthe >= operator. Read more
","PartialOrd>","actix_service::boxed::BoxFuture"],["
source§

impl<Ptr> Pin<Ptr>
where\n Ptr: Deref,\n <Ptr as Deref>::Target: Unpin,

1.33.0 (const: unstable) · source

pub fn new(pointer: Ptr) -> Pin<Ptr>

Constructs a new Pin<Ptr> around a pointer to some data of a type that\nimplements Unpin.

\n

Unlike Pin::new_unchecked, this method is safe because the pointer\nPtr dereferences to an Unpin type, which cancels the pinning guarantees.

\n
§Examples
\n
use std::pin::Pin;\n\nlet mut val: u8 = 5;\n\n// Since `val` doesn't care about being moved, we can safely create a \"facade\" `Pin`\n// which will allow `val` to participate in `Pin`-bound apis  without checking that\n// pinning guarantees are actually upheld.\nlet mut pinned: Pin<&mut u8> = Pin::new(&mut val);
\n
1.39.0 (const: unstable) · source

pub fn into_inner(pin: Pin<Ptr>) -> Ptr

Unwraps this Pin<Ptr>, returning the underlying pointer.

\n

Doing this operation safely requires that the data pointed at by this pinning pointer\nimplements Unpin so that we can ignore the pinning invariants when unwrapping it.

\n
§Examples
\n
use std::pin::Pin;\n\nlet mut val: u8 = 5;\nlet pinned: Pin<&mut u8> = Pin::new(&mut val);\n\n// Unwrap the pin to get the underlying mutable reference to the value. We can do\n// this because `val` doesn't care about being moved, so the `Pin` was just\n// a \"facade\" anyway.\nlet r = Pin::into_inner(pinned);\nassert_eq!(*r, 5);
\n
",0,"actix_service::boxed::BoxFuture"],["
source§

impl<Ptr> Pin<Ptr>
where\n Ptr: Deref,

1.33.0 (const: unstable) · source

pub unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr>

Constructs a new Pin<Ptr> around a reference to some data of a type that\nmay or may not implement Unpin.

\n

If pointer dereferences to an Unpin type, Pin::new should be used\ninstead.

\n
§Safety
\n

This constructor is unsafe because we cannot guarantee that the data\npointed to by pointer is pinned. At its core, pinning a value means making the\nguarantee that the value’s data will not be moved nor have its storage invalidated until\nit gets dropped. For a more thorough explanation of pinning, see the pin module docs.

\n

If the caller that is constructing this Pin<Ptr> does not ensure that the data Ptr\npoints to is pinned, that is a violation of the API contract and may lead to undefined\nbehavior in later (even safe) operations.

\n

By using this method, you are also making a promise about the Deref and\nDerefMut implementations of Ptr, if they exist. Most importantly, they\nmust not move out of their self arguments: Pin::as_mut and Pin::as_ref\nwill call DerefMut::deref_mut and Deref::deref on the pointer type Ptr\nand expect these methods to uphold the pinning invariants.\nMoreover, by calling this method you promise that the reference Ptr\ndereferences to will not be moved out of again; in particular, it\nmust not be possible to obtain a &mut Ptr::Target and then\nmove out of that reference (using, for example mem::swap).

\n

For example, calling Pin::new_unchecked on an &'a mut T is unsafe because\nwhile you are able to pin it for the given lifetime 'a, you have no control\nover whether it is kept pinned once 'a ends, and therefore cannot uphold the\nguarantee that a value, once pinned, remains pinned until it is dropped:

\n\n
use std::mem;\nuse std::pin::Pin;\n\nfn move_pinned_ref<T>(mut a: T, mut b: T) {\n    unsafe {\n        let p: Pin<&mut T> = Pin::new_unchecked(&mut a);\n        // This should mean the pointee `a` can never move again.\n    }\n    mem::swap(&mut a, &mut b); // Potential UB down the road ⚠️\n    // The address of `a` changed to `b`'s stack slot, so `a` got moved even\n    // though we have previously pinned it! We have violated the pinning API contract.\n}
\n

A value, once pinned, must remain pinned until it is dropped (unless its type implements\nUnpin). Because Pin<&mut T> does not own the value, dropping the Pin will not drop\nthe value and will not end the pinning contract. So moving the value after dropping the\nPin<&mut T> is still a violation of the API contract.

\n

Similarly, calling Pin::new_unchecked on an Rc<T> is unsafe because there could be\naliases to the same data that are not subject to the pinning restrictions:

\n\n
use std::rc::Rc;\nuse std::pin::Pin;\n\nfn move_pinned_rc<T>(mut x: Rc<T>) {\n    // This should mean the pointee can never move again.\n    let pin = unsafe { Pin::new_unchecked(Rc::clone(&x)) };\n    {\n        let p: Pin<&T> = pin.as_ref();\n        // ...\n    }\n    drop(pin);\n\n    let content = Rc::get_mut(&mut x).unwrap(); // Potential UB down the road ⚠️\n    // Now, if `x` was the only reference, we have a mutable reference to\n    // data that we pinned above, which we could use to move it as we have\n    // seen in the previous example. We have violated the pinning API contract.\n}
\n
§Pinning of closure captures
\n

Particular care is required when using Pin::new_unchecked in a closure:\nPin::new_unchecked(&mut var) where var is a by-value (moved) closure capture\nimplicitly makes the promise that the closure itself is pinned, and that all uses\nof this closure capture respect that pinning.

\n\n
use std::pin::Pin;\nuse std::task::Context;\nuse std::future::Future;\n\nfn move_pinned_closure(mut x: impl Future, cx: &mut Context<'_>) {\n    // Create a closure that moves `x`, and then internally uses it in a pinned way.\n    let mut closure = move || unsafe {\n        let _ignore = Pin::new_unchecked(&mut x).poll(cx);\n    };\n    // Call the closure, so the future can assume it has been pinned.\n    closure();\n    // Move the closure somewhere else. This also moves `x`!\n    let mut moved = closure;\n    // Calling it again means we polled the future from two different locations,\n    // violating the pinning API contract.\n    moved(); // Potential UB ⚠️\n}
\n

When passing a closure to another API, it might be moving the closure any time, so\nPin::new_unchecked on closure captures may only be used if the API explicitly documents\nthat the closure is pinned.

\n

The better alternative is to avoid all that trouble and do the pinning in the outer function\ninstead (here using the pin! macro):

\n\n
use std::pin::pin;\nuse std::task::Context;\nuse std::future::Future;\n\nfn move_pinned_closure(mut x: impl Future, cx: &mut Context<'_>) {\n    let mut x = pin!(x);\n    // Create a closure that captures `x: Pin<&mut _>`, which is safe to move.\n    let mut closure = move || {\n        let _ignore = x.as_mut().poll(cx);\n    };\n    // Call the closure, so the future can assume it has been pinned.\n    closure();\n    // Move the closure somewhere else.\n    let mut moved = closure;\n    // Calling it again here is fine (except that we might be polling a future that already\n    // returned `Poll::Ready`, but that is a separate problem).\n    moved();\n}
\n
1.33.0 · source

pub fn as_ref(&self) -> Pin<&<Ptr as Deref>::Target>

Gets a shared reference to the pinned value this Pin points to.

\n

This is a generic method to go from &Pin<Pointer<T>> to Pin<&T>.\nIt is safe because, as part of the contract of Pin::new_unchecked,\nthe pointee cannot move after Pin<Pointer<T>> got created.\n“Malicious” implementations of Pointer::Deref are likewise\nruled out by the contract of Pin::new_unchecked.

\n
",0,"actix_service::boxed::BoxFuture"],["
source§

impl<Ptr> Pin<Ptr>
where\n Ptr: DerefMut,

1.33.0 · source

pub fn as_mut(&mut self) -> Pin<&mut <Ptr as Deref>::Target>

Gets a mutable reference to the pinned value this Pin<Ptr> points to.

\n

This is a generic method to go from &mut Pin<Pointer<T>> to Pin<&mut T>.\nIt is safe because, as part of the contract of Pin::new_unchecked,\nthe pointee cannot move after Pin<Pointer<T>> got created.\n“Malicious” implementations of Pointer::DerefMut are likewise\nruled out by the contract of Pin::new_unchecked.

\n

This method is useful when doing multiple calls to functions that consume the\npinning pointer.

\n
§Example
\n
use std::pin::Pin;\n\nimpl Type {\n    fn method(self: Pin<&mut Self>) {\n        // do something\n    }\n\n    fn call_method_twice(mut self: Pin<&mut Self>) {\n        // `method` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.\n        self.as_mut().method();\n        self.as_mut().method();\n    }\n}
\n
source

pub fn as_deref_mut(\n self: Pin<&mut Pin<Ptr>>,\n) -> Pin<&mut <Ptr as Deref>::Target>

🔬This is a nightly-only experimental API. (pin_deref_mut)

Gets Pin<&mut T> to the underlying pinned value from this nested Pin-pointer.

\n

This is a generic method to go from Pin<&mut Pin<Pointer<T>>> to Pin<&mut T>. It is\nsafe because the existence of a Pin<Pointer<T>> ensures that the pointee, T, cannot\nmove in the future, and this method does not enable the pointee to move. “Malicious”\nimplementations of Ptr::DerefMut are likewise ruled out by the contract of\nPin::new_unchecked.

\n
1.33.0 · source

pub fn set(&mut self, value: <Ptr as Deref>::Target)
where\n <Ptr as Deref>::Target: Sized,

Assigns a new value to the memory location pointed to by the Pin<Ptr>.

\n

This overwrites pinned data, but that is okay: the original pinned value’s destructor gets\nrun before being overwritten and the new value is also a valid value of the same type, so\nno pinning invariant is violated. See the pin module documentation\nfor more information on how this upholds the pinning invariants.

\n
§Example
\n
use std::pin::Pin;\n\nlet mut val: u8 = 5;\nlet mut pinned: Pin<&mut u8> = Pin::new(&mut val);\nprintln!(\"{}\", pinned); // 5\npinned.set(10);\nprintln!(\"{}\", pinned); // 10
\n
",0,"actix_service::boxed::BoxFuture"],["
source§

impl<Ptr> Pin<Ptr>
where\n Ptr: Deref,

1.39.0 (const: unstable) · source

pub unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr

Unwraps this Pin<Ptr>, returning the underlying Ptr.

\n
§Safety
\n

This function is unsafe. You must guarantee that you will continue to\ntreat the pointer Ptr as pinned after you call this function, so that\nthe invariants on the Pin type can be upheld. If the code using the\nresulting Ptr does not continue to maintain the pinning invariants that\nis a violation of the API contract and may lead to undefined behavior in\nlater (safe) operations.

\n

Note that you must be able to guarantee that the data pointed to by Ptr\nwill be treated as pinned all the way until its drop handler is complete!

\n

For more information, see the pin module docs

\n

If the underlying data is Unpin, Pin::into_inner should be used\ninstead.

\n
",0,"actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr> Pointer for Pin<Ptr>
where\n Ptr: Pointer,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
","Pointer","actix_service::boxed::BoxFuture"],["
§

impl<P> Stream for Pin<P>
where\n P: DerefMut + Unpin,\n <P as Deref>::Target: Stream,

§

type Item = <<P as Deref>::Target as Stream>::Item

Values yielded by the stream.
§

fn poll_next(\n self: Pin<&mut Pin<P>>,\n cx: &mut Context<'_>,\n) -> Poll<Option<<Pin<P> as Stream>::Item>>

Attempt to pull out the next value of this stream, registering the\ncurrent task for wakeup if the value is not yet available, and returning\nNone if the stream is exhausted. Read more
§

fn size_hint(&self) -> (usize, Option<usize>)

Returns the bounds on the remaining length of the stream. Read more
","Stream","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr>

","CoerceUnsized>","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr> Copy for Pin<Ptr>
where\n Ptr: Copy,

","Copy","actix_service::boxed::BoxFuture"],["
source§

impl<Ptr> DerefPure for Pin<Ptr>
where\n Ptr: DerefPure,

","DerefPure","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr>

","DispatchFromDyn>","actix_service::boxed::BoxFuture"],["
1.41.0 · source§

impl<Ptr> Eq for Pin<Ptr>
where\n Ptr: Deref,\n <Ptr as Deref>::Target: Eq,

","Eq","actix_service::boxed::BoxFuture"],["
1.33.0 · source§

impl<T> PinCoerceUnsized for Pin<T>
where\n T: PinCoerceUnsized,

","PinCoerceUnsized","actix_service::boxed::BoxFuture"]]]]); + if (window.register_type_impls) { + window.register_type_impls(type_impls); + } else { + window.pending_type_impls = type_impls; + } +})() +//{"start":55,"fragment_lengths":[100168]} \ No newline at end of file