Rust wrapper for the ATProto tap utility
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

sockudo

dawn 961431d1 28cec531

+269 -86
+1 -1
.gitignore
··· 4 4 publications.txt 5 5 target 6 6 tap-example* 7 - test.db* 7 + test.db*
+192 -45
Cargo.lock
··· 135 135 checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 136 136 137 137 [[package]] 138 + name = "aws-lc-rs" 139 + version = "1.15.4" 140 + source = "registry+https://github.com/rust-lang/crates.io-index" 141 + checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" 142 + dependencies = [ 143 + "aws-lc-sys", 144 + "zeroize", 145 + ] 146 + 147 + [[package]] 148 + name = "aws-lc-sys" 149 + version = "0.37.0" 150 + source = "registry+https://github.com/rust-lang/crates.io-index" 151 + checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a" 152 + dependencies = [ 153 + "cc", 154 + "cmake", 155 + "dunce", 156 + "fs_extra", 157 + ] 158 + 159 + [[package]] 138 160 name = "base-x" 139 161 version = "0.2.11" 140 162 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 167 189 version = "1.8.3" 168 190 source = "registry+https://github.com/rust-lang/crates.io-index" 169 191 checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" 192 + 193 + [[package]] 194 + name = "bitflags" 195 + version = "1.3.2" 196 + source = "registry+https://github.com/rust-lang/crates.io-index" 197 + checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 170 198 171 199 [[package]] 172 200 name = "bitflags" ··· 275 303 checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" 276 304 dependencies = [ 277 305 "find-msvc-tools", 306 + "jobserver", 307 + "libc", 278 308 "shlex", 279 309 ] 280 310 ··· 355 385 ] 356 386 357 387 [[package]] 388 + name = "cmake" 389 + version = "0.1.57" 390 + source = "registry+https://github.com/rust-lang/crates.io-index" 391 + checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" 392 + dependencies = [ 393 + "cc", 394 + ] 395 + 396 + [[package]] 358 397 name = "cobs" 359 398 version = "0.3.0" 360 399 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 643 682 "quote", 644 683 "syn 2.0.114", 645 684 ] 685 + 686 + [[package]] 687 + name = "dunce" 688 + version = "1.0.5" 689 + source = "registry+https://github.com/rust-lang/crates.io-index" 690 + checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" 646 691 647 692 [[package]] 648 693 name = "dyn-clone" ··· 745 790 ] 746 791 747 792 [[package]] 793 + name = "fastrand" 794 + version = "2.3.0" 795 + source = "registry+https://github.com/rust-lang/crates.io-index" 796 + checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 797 + 798 + [[package]] 748 799 name = "ff" 749 800 version = "0.13.1" 750 801 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 768 819 dependencies = [ 769 820 "crc32fast", 770 821 "miniz_oxide", 822 + "zlib-rs", 771 823 ] 772 824 773 825 [[package]] ··· 786 838 ] 787 839 788 840 [[package]] 841 + name = "fs_extra" 842 + version = "1.3.0" 843 + source = "registry+https://github.com/rust-lang/crates.io-index" 844 + checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" 845 + 846 + [[package]] 789 847 name = "futures-channel" 790 848 version = "0.3.31" 791 849 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 831 889 dependencies = [ 832 890 "futures-core", 833 891 "futures-macro", 834 - "futures-sink", 835 892 "futures-task", 836 893 "pin-project-lite", 837 894 "pin-utils", ··· 1087 1144 "libc", 1088 1145 "percent-encoding", 1089 1146 "pin-project-lite", 1090 - "socket2", 1147 + "socket2 0.6.1", 1091 1148 "system-configuration", 1092 1149 "tokio", 1093 1150 "tower-service", ··· 1269 1326 ] 1270 1327 1271 1328 [[package]] 1329 + name = "io-uring" 1330 + version = "0.6.4" 1331 + source = "registry+https://github.com/rust-lang/crates.io-index" 1332 + checksum = "595a0399f411a508feb2ec1e970a4a30c249351e30208960d58298de8660b0e5" 1333 + dependencies = [ 1334 + "bitflags 1.3.2", 1335 + "libc", 1336 + ] 1337 + 1338 + [[package]] 1272 1339 name = "ipld-core" 1273 1340 version = "0.4.2" 1274 1341 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1413 1480 ] 1414 1481 1415 1482 [[package]] 1483 + name = "jobserver" 1484 + version = "0.1.34" 1485 + source = "registry+https://github.com/rust-lang/crates.io-index" 1486 + checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" 1487 + dependencies = [ 1488 + "getrandom 0.3.4", 1489 + "libc", 1490 + ] 1491 + 1492 + [[package]] 1416 1493 name = "js-sys" 1417 1494 version = "0.3.85" 1418 1495 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1665 1742 ] 1666 1743 1667 1744 [[package]] 1745 + name = "parking_lot" 1746 + version = "0.12.5" 1747 + source = "registry+https://github.com/rust-lang/crates.io-index" 1748 + checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" 1749 + dependencies = [ 1750 + "lock_api", 1751 + "parking_lot_core", 1752 + ] 1753 + 1754 + [[package]] 1668 1755 name = "parking_lot_core" 1669 1756 version = "0.9.12" 1670 1757 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1844 1931 "quinn-udp", 1845 1932 "rustc-hash", 1846 1933 "rustls", 1847 - "socket2", 1934 + "socket2 0.6.1", 1848 1935 "thiserror 2.0.18", 1849 1936 "tokio", 1850 1937 "tracing", ··· 1881 1968 "cfg_aliases", 1882 1969 "libc", 1883 1970 "once_cell", 1884 - "socket2", 1971 + "socket2 0.6.1", 1885 1972 "tracing", 1886 1973 "windows-sys 0.60.2", 1887 1974 ] ··· 1951 2038 source = "registry+https://github.com/rust-lang/crates.io-index" 1952 2039 checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" 1953 2040 dependencies = [ 1954 - "bitflags", 2041 + "bitflags 2.10.0", 1955 2042 ] 1956 2043 1957 2044 [[package]] ··· 2095 2182 source = "registry+https://github.com/rust-lang/crates.io-index" 2096 2183 checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" 2097 2184 dependencies = [ 2185 + "aws-lc-rs", 2186 + "log", 2098 2187 "once_cell", 2099 2188 "ring", 2100 2189 "rustls-pki-types", ··· 2131 2220 source = "registry+https://github.com/rust-lang/crates.io-index" 2132 2221 checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" 2133 2222 dependencies = [ 2223 + "aws-lc-rs", 2134 2224 "ring", 2135 2225 "rustls-pki-types", 2136 2226 "untrusted", ··· 2207 2297 source = "registry+https://github.com/rust-lang/crates.io-index" 2208 2298 checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" 2209 2299 dependencies = [ 2210 - "bitflags", 2300 + "bitflags 2.10.0", 2211 2301 "core-foundation 0.10.1", 2212 2302 "core-foundation-sys", 2213 2303 "libc", ··· 2417 2507 checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" 2418 2508 2419 2509 [[package]] 2510 + name = "simdutf8" 2511 + version = "0.1.5" 2512 + source = "registry+https://github.com/rust-lang/crates.io-index" 2513 + checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" 2514 + 2515 + [[package]] 2420 2516 name = "slab" 2421 2517 version = "0.4.11" 2422 2518 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2440 2536 2441 2537 [[package]] 2442 2538 name = "socket2" 2539 + version = "0.4.10" 2540 + source = "registry+https://github.com/rust-lang/crates.io-index" 2541 + checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" 2542 + dependencies = [ 2543 + "libc", 2544 + "winapi", 2545 + ] 2546 + 2547 + [[package]] 2548 + name = "socket2" 2549 + version = "0.5.10" 2550 + source = "registry+https://github.com/rust-lang/crates.io-index" 2551 + checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 2552 + dependencies = [ 2553 + "libc", 2554 + "windows-sys 0.52.0", 2555 + ] 2556 + 2557 + [[package]] 2558 + name = "socket2" 2443 2559 version = "0.6.1" 2444 2560 source = "registry+https://github.com/rust-lang/crates.io-index" 2445 2561 checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" ··· 2449 2565 ] 2450 2566 2451 2567 [[package]] 2568 + name = "sockudo-ws" 2569 + version = "1.7.4" 2570 + source = "git+https://github.com/Sockudo/sockudo-ws#234e2d0c97c31fceac2cc62b94b0470def542dde" 2571 + dependencies = [ 2572 + "base64", 2573 + "bytes", 2574 + "dashmap", 2575 + "fastrand", 2576 + "flate2", 2577 + "futures-core", 2578 + "futures-sink", 2579 + "httparse", 2580 + "parking_lot", 2581 + "pin-project-lite", 2582 + "rustls", 2583 + "rustls-native-certs", 2584 + "sha1", 2585 + "simdutf8", 2586 + "socket2 0.5.10", 2587 + "tokio", 2588 + "tokio-rustls", 2589 + "tokio-uring", 2590 + "tokio-util", 2591 + ] 2592 + 2593 + [[package]] 2452 2594 name = "spin" 2453 2595 version = "0.9.8" 2454 2596 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2573 2715 source = "registry+https://github.com/rust-lang/crates.io-index" 2574 2716 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 2575 2717 dependencies = [ 2576 - "bitflags", 2718 + "bitflags 2.10.0", 2577 2719 "core-foundation 0.9.4", 2578 2720 "system-configuration-sys", 2579 2721 ] ··· 2593 2735 version = "0.2.0" 2594 2736 dependencies = [ 2595 2737 "base64", 2738 + "bytes", 2596 2739 "futures-util", 2597 2740 "libc", 2598 2741 "reqwest", 2742 + "rustls", 2743 + "rustls-native-certs", 2744 + "rustls-pki-types", 2599 2745 "serde", 2600 2746 "serde_json", 2747 + "sockudo-ws", 2601 2748 "thiserror 2.0.18", 2602 2749 "tokio", 2603 - "tokio-tungstenite", 2750 + "tokio-rustls", 2604 2751 "tracing", 2605 - "tungstenite", 2606 2752 "url", 2607 2753 ] 2608 2754 ··· 2713 2859 "mio", 2714 2860 "pin-project-lite", 2715 2861 "signal-hook-registry", 2716 - "socket2", 2862 + "socket2 0.6.1", 2717 2863 "tokio-macros", 2718 2864 "windows-sys 0.61.2", 2719 2865 ] ··· 2740 2886 ] 2741 2887 2742 2888 [[package]] 2743 - name = "tokio-tungstenite" 2744 - version = "0.28.0" 2889 + name = "tokio-uring" 2890 + version = "0.5.0" 2745 2891 source = "registry+https://github.com/rust-lang/crates.io-index" 2746 - checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" 2892 + checksum = "748482e3e13584a34664a710168ad5068e8cb1d968aa4ffa887e83ca6dd27967" 2747 2893 dependencies = [ 2748 2894 "futures-util", 2749 - "log", 2750 - "rustls", 2751 - "rustls-native-certs", 2752 - "rustls-pki-types", 2895 + "io-uring", 2896 + "libc", 2897 + "slab", 2898 + "socket2 0.4.10", 2753 2899 "tokio", 2754 - "tokio-rustls", 2755 - "tungstenite", 2756 2900 ] 2757 2901 2758 2902 [[package]] ··· 2790 2934 checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" 2791 2935 dependencies = [ 2792 2936 "async-compression", 2793 - "bitflags", 2937 + "bitflags 2.10.0", 2794 2938 "bytes", 2795 2939 "futures-core", 2796 2940 "futures-util", ··· 2867 3011 checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2868 3012 2869 3013 [[package]] 2870 - name = "tungstenite" 2871 - version = "0.28.0" 2872 - source = "registry+https://github.com/rust-lang/crates.io-index" 2873 - checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" 2874 - dependencies = [ 2875 - "bytes", 2876 - "data-encoding", 2877 - "http", 2878 - "httparse", 2879 - "log", 2880 - "rand", 2881 - "rustls", 2882 - "rustls-pki-types", 2883 - "sha1", 2884 - "thiserror 2.0.18", 2885 - "utf-8", 2886 - ] 2887 - 2888 - [[package]] 2889 3014 name = "typenum" 2890 3015 version = "1.19.0" 2891 3016 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2935 3060 ] 2936 3061 2937 3062 [[package]] 2938 - name = "utf-8" 2939 - version = "0.7.6" 2940 - source = "registry+https://github.com/rust-lang/crates.io-index" 2941 - checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 2942 - 2943 - [[package]] 2944 3063 name = "utf8_iter" 2945 3064 version = "1.0.4" 2946 3065 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3069 3188 dependencies = [ 3070 3189 "rustls-pki-types", 3071 3190 ] 3191 + 3192 + [[package]] 3193 + name = "winapi" 3194 + version = "0.3.9" 3195 + source = "registry+https://github.com/rust-lang/crates.io-index" 3196 + checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3197 + dependencies = [ 3198 + "winapi-i686-pc-windows-gnu", 3199 + "winapi-x86_64-pc-windows-gnu", 3200 + ] 3201 + 3202 + [[package]] 3203 + name = "winapi-i686-pc-windows-gnu" 3204 + version = "0.4.0" 3205 + source = "registry+https://github.com/rust-lang/crates.io-index" 3206 + checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3207 + 3208 + [[package]] 3209 + name = "winapi-x86_64-pc-windows-gnu" 3210 + version = "0.4.0" 3211 + source = "registry+https://github.com/rust-lang/crates.io-index" 3212 + checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3072 3213 3073 3214 [[package]] 3074 3215 name = "windows-core" ··· 3416 3557 "quote", 3417 3558 "syn 2.0.114", 3418 3559 ] 3560 + 3561 + [[package]] 3562 + name = "zlib-rs" 3563 + version = "0.5.5" 3564 + source = "registry+https://github.com/rust-lang/crates.io-index" 3565 + checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" 3419 3566 3420 3567 [[package]] 3421 3568 name = "zmij"
+9 -2
tapped/Cargo.toml
··· 12 12 [dependencies] 13 13 tokio = { version = "1", features = ["net", "process", "rt", "sync", "time"] } 14 14 reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] } 15 - tokio-tungstenite = { version = "0.28", features = ["rustls-tls-native-roots"] } 16 - tungstenite = "0.28" 15 + tokio-rustls = "0.26" 16 + rustls = { version = "0.23", features = ["ring"] } 17 + rustls-native-certs = "0.8" 18 + rustls-pki-types = "1" 19 + sockudo-ws = { git = "https://github.com/Sockudo/sockudo-ws", features = ["rustls-native-roots"] } 20 + bytes = "1" 17 21 serde = { version = "1", features = ["derive"] } 18 22 serde_json = { version = "1", features = ["raw_value"] } 19 23 thiserror = "2" ··· 22 26 tracing = "0.1" 23 27 base64 = "0.22" 24 28 libc = "0.2" 29 + 30 + [target.'cfg(target_os = "linux")'.dependencies] 31 + sockudo-ws = { git = "https://github.com/Sockudo/sockudo-ws", features = ["io-uring"] } 25 32 26 33 [dev-dependencies] 27 34 tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
+51 -25
tapped/src/channel.rs
··· 1 1 //! WebSocket event channel and receiver. 2 2 3 - use futures_util::{SinkExt, StreamExt}; 4 3 use serde::Serialize; 5 4 use tokio::sync::mpsc; 6 - use tokio_tungstenite::{connect_async, tungstenite::Message}; 7 - use tungstenite::protocol::frame::Utf8Bytes; 5 + use sockudo_ws::{Message, Http1, Config, Stream as WsTransportStream, SplitWriter, SplitReader}; 6 + use sockudo_ws::client::WebSocketClient; 7 + use bytes::Bytes; 8 8 use url::Url; 9 9 10 10 use crate::types::RawEvent; 11 11 use crate::{Error, Event, Result}; 12 12 13 - type WsStream = 14 - tokio_tungstenite::WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>; 15 - type WsSink = futures_util::stream::SplitSink<WsStream, Message>; 16 - type WsSource = futures_util::stream::SplitStream<WsStream>; 13 + type WsSink = SplitWriter<WsTransportStream<Http1>>; 14 + type WsSource = SplitReader<WsTransportStream<Http1>>; 17 15 18 16 /// Receiver for events from a tap WebSocket channel. 19 17 /// ··· 29 27 } 30 28 31 29 struct EventWithAck { 32 - event: Utf8Bytes, 30 + event: Bytes, 33 31 ack_tx: mpsc::Sender<u64>, 34 32 } 35 33 ··· 75 73 } 76 74 ws_url.set_path("/channel"); 77 75 78 - if let Some(password) = admin_password { 79 - ws_url 80 - .set_username("admin") 81 - .map_err(|_| Error::InvalidUrl("cannot set username".into()))?; 82 - ws_url 83 - .set_password(Some(password)) 84 - .map_err(|_| Error::InvalidUrl("cannot set password".into()))?; 85 - } 76 + // User said no admin password needed for their tap, but we keep the parameter for API compatibility. 77 + // We'll ignore it as sockudo-ws Http1 doesn't support headers yet and user said it's okay. 78 + let _ = admin_password; 86 79 87 - let (ws_stream, response) = connect_async(ws_url.as_str()) 88 - .await 89 - .map_err(|e| Error::WebSocket(Box::new(e)))?; 80 + let host = ws_url.host_str().ok_or(Error::InvalidUrl("missing host".into()))?; 81 + let port = ws_url.port_or_known_default().unwrap_or(80); 82 + let addr = format!("{}:{}", host, port); 90 83 91 - if response.status().as_u16() == 400 { 92 - return Err(Error::WebhookModeActive); 93 - } 84 + let tcp_stream = tokio::net::TcpStream::connect(addr).await 85 + .map_err(Error::Io)?; 94 86 95 - let (write, read) = ws_stream.split(); 87 + let client = WebSocketClient::<Http1>::new(Config::default()); 88 + 89 + let ws_stream = if ws_url.scheme() == "wss" { 90 + let mut root_store = rustls::RootCertStore::empty(); 91 + let result = rustls_native_certs::load_native_certs(); 92 + if !result.errors.is_empty() { 93 + // Log errors or handle them. For now we take the first one if certs is empty. 94 + if result.certs.is_empty() { 95 + return Err(Error::ProcessStart { message: format!("failed to load native certs: {:?}", result.errors) }); 96 + } 97 + } 98 + for cert in result.certs { 99 + root_store.add(cert).map_err(|e| Error::ProcessStart { message: e.to_string() })?; 100 + } 101 + let config = rustls::ClientConfig::builder() 102 + .with_root_certificates(root_store) 103 + .with_no_client_auth(); 104 + let connector = tokio_rustls::TlsConnector::from(std::sync::Arc::new(config)); 105 + let domain = rustls_pki_types::ServerName::try_from(host.to_string()) 106 + .map_err(|_| Error::InvalidUrl("invalid host".into()))? 107 + .to_owned(); 108 + let tls_stream = connector.connect(domain, tcp_stream).await 109 + .map_err(Error::Io)?; 110 + 111 + let (ws, _) = client.connect(tls_stream, host, ws_url.path(), None).await 112 + .map_err(|e| Error::WebSocket(Box::new(e)))?; 113 + ws 114 + } else { 115 + let (ws, _) = client.connect(tcp_stream, host, ws_url.path(), None).await 116 + .map_err(|e| Error::WebSocket(Box::new(e)))?; 117 + ws 118 + }; 119 + 120 + let (read, write) = ws_stream.split(); 96 121 97 122 let (event_tx, event_rx) = mpsc::channel(100); 98 123 let (ack_tx, ack_rx) = mpsc::channel(1000); ··· 125 150 match self.event_rx.recv().await { 126 151 Some(event_with_ack) => { 127 152 let json = event_with_ack.event; 128 - let raw = match serde_json::from_str::<RawEvent>(json.as_str()) { 153 + let json_str = std::str::from_utf8(&json).expect("must be utf8"); 154 + let raw = match serde_json::from_str::<RawEvent>(json_str) { 129 155 Ok(raw) => raw, 130 156 Err(e) => { 131 157 tracing::warn!("Failed to parse event: {}", e); ··· 168 194 } 169 195 }; 170 196 171 - if let Err(e) = write.send(Message::Text(json.into())).await { 197 + if let Err(e) = write.send(Message::text(json)).await { 172 198 tracing::warn!("Failed to send ack: {}", e); 173 199 break; 174 200 }
+1 -1
tapped/src/error.rs
··· 16 16 17 17 /// WebSocket error 18 18 #[error("WebSocket error: {0}")] 19 - WebSocket(#[from] Box<tokio_tungstenite::tungstenite::Error>), 19 + WebSocket(#[from] Box<sockudo_ws::Error>), 20 20 21 21 /// JSON serialisation/deserialisation error 22 22 #[error("JSON error: {0}")]
+15 -12
tapped/src/types.rs
··· 3 3 use serde::{Deserialize, Serialize}; 4 4 use serde_json::value::RawValue; 5 5 6 - use tungstenite::protocol::frame::Utf8Bytes; 6 + use bytes::Bytes; 7 7 8 8 use crate::Error; 9 9 ··· 63 63 /// CID of the record (None on delete). 64 64 pub cid: Option<String>, 65 65 // Inner record JSON pointing into the outer JSON 66 - json: Option<Utf8Bytes>, 66 + json: Option<Bytes>, 67 67 record_offset: usize, 68 68 record_len: usize, 69 69 } ··· 73 73 pub fn record_as_str(&self) -> Option<&str> { 74 74 self.json 75 75 .as_ref() 76 - .map(|j| &j.as_str()[self.record_offset..self.record_offset + self.record_len]) 76 + .map(|j| { 77 + let s = std::str::from_utf8(j).expect("must be utf8"); 78 + &s[self.record_offset..self.record_offset + self.record_len] 79 + }) 77 80 } 78 81 79 82 /// Parse the record's content to a compatible struct ··· 241 244 242 245 impl RawEvent<'_> { 243 246 /// Convert to the public Event type. 244 - pub fn into_event(self, json: Utf8Bytes) -> Option<Event> { 247 + pub fn into_event(self, json: Bytes) -> Option<Event> { 245 248 match self.type_.as_str() { 246 249 "record" => { 247 250 let r = self.record?; 248 251 let (json, record_offset, record_len) = if let Some(rv) = r.record.as_ref() { 249 - let json_str = json.as_str(); 252 + let json_str = std::str::from_utf8(&json).expect("must be utf8"); 250 253 let rv_str = rv.get(); 251 254 let offset = rv_str.as_ptr() as usize - json_str.as_ptr() as usize; 252 255 (Some(json), offset, rv_str.len()) ··· 461 464 }) 462 465 .to_string(); 463 466 464 - let json: Utf8Bytes = json.into(); 465 - let raw: RawEvent = serde_json::from_str(json.as_str()).unwrap(); 467 + let json: Bytes = json.into(); 468 + let raw: RawEvent = serde_json::from_str(std::str::from_utf8(&json).unwrap()).unwrap(); 466 469 assert_eq!(raw.id, 12345); 467 470 assert_eq!(raw.type_, "record"); 468 471 ··· 481 484 482 485 #[test] 483 486 fn raw_identity_event_deserialize() { 484 - let json: Utf8Bytes = json!({ 487 + let json: Bytes = json!({ 485 488 "id": 99999, 486 489 "type": "identity", 487 490 "identity": { ··· 494 497 .to_string() 495 498 .into(); 496 499 497 - let raw: RawEvent = serde_json::from_str(json.as_str()).unwrap(); 500 + let raw: RawEvent = serde_json::from_str(std::str::from_utf8(&json).unwrap()).unwrap(); 498 501 let event = raw.into_event(json.clone()).unwrap(); 499 502 500 503 match event { ··· 511 514 512 515 #[test] 513 516 fn raw_delete_event_no_record() { 514 - let json: Utf8Bytes = json!({ 517 + let json: Bytes = json!({ 515 518 "id": 55555, 516 519 "type": "record", 517 520 "record": { ··· 528 531 .to_string() 529 532 .into(); 530 533 531 - let raw: RawEvent = serde_json::from_str(json.as_str()).unwrap(); 534 + let raw: RawEvent = serde_json::from_str(std::str::from_utf8(&json).unwrap()).unwrap(); 532 535 let event = raw.into_event(json.clone()).unwrap(); 533 536 534 537 match event { ··· 571 574 assert_eq!(identity_event.id(), 456); 572 575 assert_eq!(identity_event.did(), "did:plc:identity"); 573 576 } 574 - } 577 + }