Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

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

Add HTTP(S) network stream playback support for SDL simulator

Agent-Logs-Url: https://github.com/tsirysndr/rockbox-zig/sessions/57fed2c7-24d3-41b5-812b-21add9056976

Co-authored-by: tsirysndr <15877106+tsirysndr@users.noreply.github.com>

authored by

copilot-swe-agent[bot]
tsirysndr
and committed by
GitHub
fc860346 a92b5177

+1893 -20
+1 -1
Cargo.toml
··· 6 6 "webui", 7 7 ] 8 8 resolver = "2" 9 - exclude = ["rmpc", "crates/controls"] 9 + exclude = ["rmpc", "crates/controls", "crates/netstream"] 10 10 11 11 [workspace.package] 12 12 authors = ["Tsiry Sandratraina <tsiry.sndr@fluentci.io"]
+1
apps/SOURCES
··· 26 26 #endif 27 27 menus/eq_menu.c 28 28 buffering.c 29 + streamfd.c 29 30 voice_thread.c 30 31 rbcodec_helpers.c 31 32 menus/main_menu.c
+15 -14
apps/buffering.c
··· 37 37 #endif 38 38 #include "buffering.h" 39 39 #include "linked_list.h" 40 + #include "streamfd.h" 40 41 41 42 /* Define LOGF_ENABLE to enable logf output in this file */ 42 43 /* #define LOGF_ENABLE */ ··· 177 178 static void close_fd(int *fd_p) 178 179 { 179 180 int fd = *fd_p; 180 - if (fd >= 0) { 181 - close(fd); 181 + if (fd != -1) { 182 + stream_close(fd); 182 183 *fd_p = -1; 183 184 } 184 185 } ··· 635 636 return true; 636 637 } 637 638 638 - if (h->fd < 0) { /* file closed, reopen */ 639 + if (h->fd == -1) { /* file closed, reopen */ 639 640 if (h->path[0] != '\0') 640 - h->fd = open(h->path, O_RDONLY); 641 + h->fd = stream_open(h->path, O_RDONLY); 641 642 642 - if (h->fd < 0) { 643 + if (h->fd == -1) { 643 644 /* could not open the file, truncate it where it is */ 644 645 h->filesize = h->end; 645 646 return true; 646 647 } 647 648 648 649 if (h->start) 649 - lseek(h->fd, h->start, SEEK_SET); 650 + stream_lseek(h->fd, h->start, SEEK_SET); 650 651 } 651 652 652 653 trigger_cpu_boost(); ··· 689 690 return false; /* no space for read */ 690 691 691 692 /* rc is the actual amount read */ 692 - ssize_t rc = read(h->fd, ringbuf_ptr(widx), copy_n); 693 + ssize_t rc = stream_read(h->fd, ringbuf_ptr(widx), copy_n); 693 694 694 695 if (rc <= 0) { 695 696 /* Some kind of filesystem error, maybe recoverable if not codec */ ··· 954 955 return ERR_UNSUPPORTED_TYPE; 955 956 #endif 956 957 /* Other cases: there is a little more work. */ 957 - int fd = open(file, O_RDONLY); 958 - if (fd < 0) 958 + int fd = stream_open(file, O_RDONLY); 959 + if (fd == -1) 959 960 return ERR_FILE_ERROR; 960 961 961 962 size_t size = 0; ··· 983 984 #endif /* HAVE_ALBUMART */ 984 985 985 986 if (size == 0) 986 - size = filesize(fd); 987 + size = (size_t)stream_filesize_fd(fd); 987 988 988 989 unsigned int hflags = 0; 989 990 if (type == TYPE_PACKET_AUDIO || type == TYPE_CODEC) ··· 1005 1006 if (!h) { 1006 1007 DEBUGF("%s(): failed to add handle\n", __func__); 1007 1008 mutex_unlock(&llist_mutex); 1008 - close(fd); 1009 + stream_close(fd); 1009 1010 1010 1011 /*warn playback.c if it is trying to buffer too large of an image*/ 1011 1012 if(type == TYPE_BITMAP && padded_size >= buffer_len - 64*1024) ··· 1071 1072 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id); 1072 1073 } else { 1073 1074 /* Other types will get buffered in the course of normal operations */ 1074 - close(fd); 1075 + stream_close(fd); 1075 1076 1076 1077 if (handle_id >= 0) { 1077 1078 /* Inform the buffering thread that we added a handle */ ··· 1216 1217 h->ridx = h->widx = h->data = new_index; 1217 1218 h->start = h->pos = h->end = newpos; 1218 1219 1219 - if (h->fd >= 0) 1220 - lseek(h->fd, newpos, SEEK_SET); 1220 + if (h->fd != -1) 1221 + stream_lseek(h->fd, newpos, SEEK_SET); 1221 1222 1222 1223 off_t filerem = h->filesize - newpos; 1223 1224 bool send = HLIST_NEXT(h) &&
+106
apps/streamfd.c
··· 1 + /*************************************************************************** 2 + * streamfd.c - Unified stream I/O dispatch for local files and HTTP(S) 3 + * network streams (SDL simulator build only). 4 + * 5 + * See streamfd.h for the public interface and fd-encoding documentation. 6 + ***************************************************************************/ 7 + 8 + #include "config.h" 9 + 10 + #ifdef SIMULATOR 11 + 12 + #include "streamfd.h" 13 + #include "file.h" /* for sim_open / sim_read / sim_lseek / sim_close / 14 + sim_filesize (via macros) */ 15 + #include <string.h> 16 + #include <stdint.h> 17 + #include <fcntl.h> 18 + 19 + /* ------------------------------------------------------------------ 20 + * C declarations for the Rust ABI exported by crates/netstream. 21 + * ------------------------------------------------------------------ */ 22 + extern int32_t rb_net_open (const char *url); 23 + extern int64_t rb_net_read (int32_t h, void *dst, size_t n); 24 + extern int64_t rb_net_lseek (int32_t h, int64_t off, int32_t whence); 25 + extern int64_t rb_net_len (int32_t h); 26 + extern void rb_net_close (int32_t h); 27 + 28 + /* ------------------------------------------------------------------ */ 29 + 30 + /** Convert an HTTP fd (<=STREAM_HTTP_FD_BASE) back to a Rust handle id. */ 31 + static inline int32_t http_fd_to_handle(int fd) 32 + { 33 + return (int32_t)(STREAM_HTTP_FD_BASE - fd); 34 + } 35 + 36 + /* ------------------------------------------------------------------ */ 37 + 38 + static int path_is_url(const char *path) 39 + { 40 + return (strncmp(path, "http://", 7) == 0 || 41 + strncmp(path, "https://", 8) == 0); 42 + } 43 + 44 + int stream_open(const char *path, int flags) 45 + { 46 + if (path == NULL) 47 + return -1; 48 + 49 + if (path_is_url(path)) { 50 + int32_t h = rb_net_open(path); 51 + if (h < 0) 52 + return -1; 53 + /* Map handle 0 -> -1000, handle 1 -> -1001, etc. */ 54 + return STREAM_HTTP_FD_BASE - (int)h; 55 + } 56 + 57 + return open(path, flags); 58 + } 59 + 60 + ssize_t stream_read(int fd, void *buf, size_t n) 61 + { 62 + if (stream_is_http_fd(fd)) { 63 + int64_t r = rb_net_read(http_fd_to_handle(fd), buf, n); 64 + return (ssize_t)r; 65 + } 66 + return read(fd, buf, n); 67 + } 68 + 69 + off_t stream_lseek(int fd, off_t off, int whence) 70 + { 71 + if (stream_is_http_fd(fd)) { 72 + int64_t r = rb_net_lseek(http_fd_to_handle(fd), (int64_t)off, whence); 73 + return (off_t)r; 74 + } 75 + return lseek(fd, off, whence); 76 + } 77 + 78 + int stream_close(int fd) 79 + { 80 + if (fd == -1) 81 + return 0; 82 + if (stream_is_http_fd(fd)) { 83 + rb_net_close(http_fd_to_handle(fd)); 84 + return 0; 85 + } 86 + return close(fd); 87 + } 88 + 89 + off_t stream_filesize_fd(int fd) 90 + { 91 + if (stream_is_http_fd(fd)) { 92 + int64_t len = rb_net_len(http_fd_to_handle(fd)); 93 + if (len < 0) { 94 + /* 95 + * Content-Length unknown: return a large sentinel (~2 GiB). 96 + * The buffering layer truncates h->filesize to h->end when 97 + * read() returns 0 (EOF), so this is safe for finite streams. 98 + */ 99 + return (off_t)0x7FFFFFFF; 100 + } 101 + return (off_t)len; 102 + } 103 + return filesize(fd); 104 + } 105 + 106 + #endif /* SIMULATOR */
+99
apps/streamfd.h
··· 1 + /*************************************************************************** 2 + * streamfd.h - Unified stream I/O abstraction for local files and HTTP(S) 3 + * network streams. 4 + * 5 + * In the SDL simulator build, URLs that start with "http://" or "https://" 6 + * are opened as network streams backed by the Rust "netstream" crate. 7 + * All other paths are handled by the normal simulator file system functions. 8 + * 9 + * File-descriptor encoding (simulator only): 10 + * fd == -1 : closed / unset sentinel 11 + * fd >= 0 : normal sim_* file descriptor 12 + * fd <= STREAM_HTTP_FD_BASE : HTTP stream handle 13 + * handle_id = STREAM_HTTP_FD_BASE - fd 14 + * 15 + * On non-simulator builds, every symbol reduces to the existing Rockbox 16 + * file-system macro/function so there is zero overhead and zero code change 17 + * needed in callers. 18 + ***************************************************************************/ 19 + 20 + #ifndef APPS_STREAMFD_H 21 + #define APPS_STREAMFD_H 22 + 23 + #ifdef SIMULATOR 24 + 25 + #include <sys/types.h> 26 + #include <fcntl.h> 27 + #include <stdint.h> 28 + 29 + /* Sentinel: file descriptors <= this value are HTTP stream handles. */ 30 + #define STREAM_HTTP_FD_BASE (-1000) 31 + 32 + /** Return non-zero if @p fd refers to an open HTTP stream handle. */ 33 + static inline int stream_is_http_fd(int fd) 34 + { 35 + return fd <= STREAM_HTTP_FD_BASE; 36 + } 37 + 38 + /** 39 + * Open a path. 40 + * 41 + * If @p path begins with "http://" or "https://" the request is forwarded 42 + * to the Rust network layer; otherwise a normal sim_open() is performed. 43 + * 44 + * @return A file descriptor >= 0, an HTTP handle <= STREAM_HTTP_FD_BASE, 45 + * or -1 on error. 46 + */ 47 + int stream_open(const char *path, int flags); 48 + 49 + /** 50 + * Read up to @p n bytes from @p fd into @p buf. 51 + * Routes to sim_read() for real fds, rb_net_read() for HTTP fds. 52 + */ 53 + ssize_t stream_read(int fd, void *buf, size_t n); 54 + 55 + /** 56 + * Seek within @p fd. 57 + * Routes to sim_lseek() for real fds, rb_net_lseek() for HTTP fds. 58 + */ 59 + off_t stream_lseek(int fd, off_t off, int whence); 60 + 61 + /** 62 + * Close @p fd. 63 + * Routes to sim_close() for real fds, rb_net_close() for HTTP fds. 64 + * Silently ignores fd == -1. 65 + * 66 + * @return 0 on success, -1 on error. 67 + */ 68 + int stream_close(int fd); 69 + 70 + /** 71 + * Return the total size of the stream associated with @p fd. 72 + * 73 + * For HTTP streams: the Content-Length if known, or a large sentinel 74 + * value (~2 GiB) if unknown (buffering will truncate on EOF). 75 + * For regular fds: delegates to sim_filesize(). 76 + * 77 + * @return Size in bytes, or -1 on error. 78 + */ 79 + off_t stream_filesize_fd(int fd); 80 + 81 + #else /* !SIMULATOR */ 82 + 83 + /* 84 + * Non-simulator / embedded builds: map every symbol straight through to 85 + * the native Rockbox file-system API so no code needs to change in callers. 86 + */ 87 + #include "file.h" 88 + #include <unistd.h> 89 + 90 + #define stream_is_http_fd(fd) (0) 91 + #define stream_open(path, flags) open((path), (flags)) 92 + #define stream_read(fd, buf, n) read((fd), (buf), (n)) 93 + #define stream_lseek(fd, off, whence) lseek((fd), (off), (whence)) 94 + #define stream_close(fd) close(fd) 95 + #define stream_filesize_fd(fd) filesize(fd) 96 + 97 + #endif /* SIMULATOR */ 98 + 99 + #endif /* APPS_STREAMFD_H */
+1379
crates/netstream/Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "atomic-waker" 7 + version = "1.1.2" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 10 + 11 + [[package]] 12 + name = "base64" 13 + version = "0.22.1" 14 + source = "registry+https://github.com/rust-lang/crates.io-index" 15 + checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 16 + 17 + [[package]] 18 + name = "bitflags" 19 + version = "2.11.1" 20 + source = "registry+https://github.com/rust-lang/crates.io-index" 21 + checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" 22 + 23 + [[package]] 24 + name = "bumpalo" 25 + version = "3.20.2" 26 + source = "registry+https://github.com/rust-lang/crates.io-index" 27 + checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" 28 + 29 + [[package]] 30 + name = "bytes" 31 + version = "1.11.1" 32 + source = "registry+https://github.com/rust-lang/crates.io-index" 33 + checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" 34 + 35 + [[package]] 36 + name = "cc" 37 + version = "1.2.60" 38 + source = "registry+https://github.com/rust-lang/crates.io-index" 39 + checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" 40 + dependencies = [ 41 + "find-msvc-tools", 42 + "shlex", 43 + ] 44 + 45 + [[package]] 46 + name = "cfg-if" 47 + version = "1.0.4" 48 + source = "registry+https://github.com/rust-lang/crates.io-index" 49 + checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 50 + 51 + [[package]] 52 + name = "cfg_aliases" 53 + version = "0.2.1" 54 + source = "registry+https://github.com/rust-lang/crates.io-index" 55 + checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 56 + 57 + [[package]] 58 + name = "displaydoc" 59 + version = "0.2.5" 60 + source = "registry+https://github.com/rust-lang/crates.io-index" 61 + checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 62 + dependencies = [ 63 + "proc-macro2", 64 + "quote", 65 + "syn", 66 + ] 67 + 68 + [[package]] 69 + name = "find-msvc-tools" 70 + version = "0.1.9" 71 + source = "registry+https://github.com/rust-lang/crates.io-index" 72 + checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" 73 + 74 + [[package]] 75 + name = "form_urlencoded" 76 + version = "1.2.2" 77 + source = "registry+https://github.com/rust-lang/crates.io-index" 78 + checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 79 + dependencies = [ 80 + "percent-encoding", 81 + ] 82 + 83 + [[package]] 84 + name = "futures-channel" 85 + version = "0.3.32" 86 + source = "registry+https://github.com/rust-lang/crates.io-index" 87 + checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" 88 + dependencies = [ 89 + "futures-core", 90 + "futures-sink", 91 + ] 92 + 93 + [[package]] 94 + name = "futures-core" 95 + version = "0.3.32" 96 + source = "registry+https://github.com/rust-lang/crates.io-index" 97 + checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" 98 + 99 + [[package]] 100 + name = "futures-io" 101 + version = "0.3.32" 102 + source = "registry+https://github.com/rust-lang/crates.io-index" 103 + checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" 104 + 105 + [[package]] 106 + name = "futures-sink" 107 + version = "0.3.32" 108 + source = "registry+https://github.com/rust-lang/crates.io-index" 109 + checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" 110 + 111 + [[package]] 112 + name = "futures-task" 113 + version = "0.3.32" 114 + source = "registry+https://github.com/rust-lang/crates.io-index" 115 + checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" 116 + 117 + [[package]] 118 + name = "futures-util" 119 + version = "0.3.32" 120 + source = "registry+https://github.com/rust-lang/crates.io-index" 121 + checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" 122 + dependencies = [ 123 + "futures-core", 124 + "futures-io", 125 + "futures-sink", 126 + "futures-task", 127 + "memchr", 128 + "pin-project-lite", 129 + "slab", 130 + ] 131 + 132 + [[package]] 133 + name = "getrandom" 134 + version = "0.2.17" 135 + source = "registry+https://github.com/rust-lang/crates.io-index" 136 + checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" 137 + dependencies = [ 138 + "cfg-if", 139 + "js-sys", 140 + "libc", 141 + "wasi", 142 + "wasm-bindgen", 143 + ] 144 + 145 + [[package]] 146 + name = "getrandom" 147 + version = "0.3.4" 148 + source = "registry+https://github.com/rust-lang/crates.io-index" 149 + checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" 150 + dependencies = [ 151 + "cfg-if", 152 + "js-sys", 153 + "libc", 154 + "r-efi", 155 + "wasip2", 156 + "wasm-bindgen", 157 + ] 158 + 159 + [[package]] 160 + name = "http" 161 + version = "1.4.0" 162 + source = "registry+https://github.com/rust-lang/crates.io-index" 163 + checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" 164 + dependencies = [ 165 + "bytes", 166 + "itoa", 167 + ] 168 + 169 + [[package]] 170 + name = "http-body" 171 + version = "1.0.1" 172 + source = "registry+https://github.com/rust-lang/crates.io-index" 173 + checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 174 + dependencies = [ 175 + "bytes", 176 + "http", 177 + ] 178 + 179 + [[package]] 180 + name = "http-body-util" 181 + version = "0.1.3" 182 + source = "registry+https://github.com/rust-lang/crates.io-index" 183 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 184 + dependencies = [ 185 + "bytes", 186 + "futures-core", 187 + "http", 188 + "http-body", 189 + "pin-project-lite", 190 + ] 191 + 192 + [[package]] 193 + name = "httparse" 194 + version = "1.10.1" 195 + source = "registry+https://github.com/rust-lang/crates.io-index" 196 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 197 + 198 + [[package]] 199 + name = "hyper" 200 + version = "1.9.0" 201 + source = "registry+https://github.com/rust-lang/crates.io-index" 202 + checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" 203 + dependencies = [ 204 + "atomic-waker", 205 + "bytes", 206 + "futures-channel", 207 + "futures-core", 208 + "http", 209 + "http-body", 210 + "httparse", 211 + "itoa", 212 + "pin-project-lite", 213 + "smallvec", 214 + "tokio", 215 + "want", 216 + ] 217 + 218 + [[package]] 219 + name = "hyper-rustls" 220 + version = "0.27.9" 221 + source = "registry+https://github.com/rust-lang/crates.io-index" 222 + checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" 223 + dependencies = [ 224 + "http", 225 + "hyper", 226 + "hyper-util", 227 + "rustls", 228 + "tokio", 229 + "tokio-rustls", 230 + "tower-service", 231 + "webpki-roots", 232 + ] 233 + 234 + [[package]] 235 + name = "hyper-util" 236 + version = "0.1.20" 237 + source = "registry+https://github.com/rust-lang/crates.io-index" 238 + checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" 239 + dependencies = [ 240 + "base64", 241 + "bytes", 242 + "futures-channel", 243 + "futures-util", 244 + "http", 245 + "http-body", 246 + "hyper", 247 + "ipnet", 248 + "libc", 249 + "percent-encoding", 250 + "pin-project-lite", 251 + "socket2", 252 + "tokio", 253 + "tower-service", 254 + "tracing", 255 + ] 256 + 257 + [[package]] 258 + name = "icu_collections" 259 + version = "2.2.0" 260 + source = "registry+https://github.com/rust-lang/crates.io-index" 261 + checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" 262 + dependencies = [ 263 + "displaydoc", 264 + "potential_utf", 265 + "utf8_iter", 266 + "yoke", 267 + "zerofrom", 268 + "zerovec", 269 + ] 270 + 271 + [[package]] 272 + name = "icu_locale_core" 273 + version = "2.2.0" 274 + source = "registry+https://github.com/rust-lang/crates.io-index" 275 + checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" 276 + dependencies = [ 277 + "displaydoc", 278 + "litemap", 279 + "tinystr", 280 + "writeable", 281 + "zerovec", 282 + ] 283 + 284 + [[package]] 285 + name = "icu_normalizer" 286 + version = "2.2.0" 287 + source = "registry+https://github.com/rust-lang/crates.io-index" 288 + checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" 289 + dependencies = [ 290 + "icu_collections", 291 + "icu_normalizer_data", 292 + "icu_properties", 293 + "icu_provider", 294 + "smallvec", 295 + "zerovec", 296 + ] 297 + 298 + [[package]] 299 + name = "icu_normalizer_data" 300 + version = "2.2.0" 301 + source = "registry+https://github.com/rust-lang/crates.io-index" 302 + checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" 303 + 304 + [[package]] 305 + name = "icu_properties" 306 + version = "2.2.0" 307 + source = "registry+https://github.com/rust-lang/crates.io-index" 308 + checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" 309 + dependencies = [ 310 + "icu_collections", 311 + "icu_locale_core", 312 + "icu_properties_data", 313 + "icu_provider", 314 + "zerotrie", 315 + "zerovec", 316 + ] 317 + 318 + [[package]] 319 + name = "icu_properties_data" 320 + version = "2.2.0" 321 + source = "registry+https://github.com/rust-lang/crates.io-index" 322 + checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" 323 + 324 + [[package]] 325 + name = "icu_provider" 326 + version = "2.2.0" 327 + source = "registry+https://github.com/rust-lang/crates.io-index" 328 + checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" 329 + dependencies = [ 330 + "displaydoc", 331 + "icu_locale_core", 332 + "writeable", 333 + "yoke", 334 + "zerofrom", 335 + "zerotrie", 336 + "zerovec", 337 + ] 338 + 339 + [[package]] 340 + name = "idna" 341 + version = "1.1.0" 342 + source = "registry+https://github.com/rust-lang/crates.io-index" 343 + checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" 344 + dependencies = [ 345 + "idna_adapter", 346 + "smallvec", 347 + "utf8_iter", 348 + ] 349 + 350 + [[package]] 351 + name = "idna_adapter" 352 + version = "1.2.1" 353 + source = "registry+https://github.com/rust-lang/crates.io-index" 354 + checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 355 + dependencies = [ 356 + "icu_normalizer", 357 + "icu_properties", 358 + ] 359 + 360 + [[package]] 361 + name = "ipnet" 362 + version = "2.12.0" 363 + source = "registry+https://github.com/rust-lang/crates.io-index" 364 + checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" 365 + 366 + [[package]] 367 + name = "iri-string" 368 + version = "0.7.12" 369 + source = "registry+https://github.com/rust-lang/crates.io-index" 370 + checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" 371 + dependencies = [ 372 + "memchr", 373 + "serde", 374 + ] 375 + 376 + [[package]] 377 + name = "itoa" 378 + version = "1.0.18" 379 + source = "registry+https://github.com/rust-lang/crates.io-index" 380 + checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" 381 + 382 + [[package]] 383 + name = "js-sys" 384 + version = "0.3.95" 385 + source = "registry+https://github.com/rust-lang/crates.io-index" 386 + checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" 387 + dependencies = [ 388 + "cfg-if", 389 + "futures-util", 390 + "once_cell", 391 + "wasm-bindgen", 392 + ] 393 + 394 + [[package]] 395 + name = "libc" 396 + version = "0.2.185" 397 + source = "registry+https://github.com/rust-lang/crates.io-index" 398 + checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" 399 + 400 + [[package]] 401 + name = "litemap" 402 + version = "0.8.2" 403 + source = "registry+https://github.com/rust-lang/crates.io-index" 404 + checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" 405 + 406 + [[package]] 407 + name = "log" 408 + version = "0.4.29" 409 + source = "registry+https://github.com/rust-lang/crates.io-index" 410 + checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" 411 + 412 + [[package]] 413 + name = "lru-slab" 414 + version = "0.1.2" 415 + source = "registry+https://github.com/rust-lang/crates.io-index" 416 + checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 417 + 418 + [[package]] 419 + name = "memchr" 420 + version = "2.8.0" 421 + source = "registry+https://github.com/rust-lang/crates.io-index" 422 + checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" 423 + 424 + [[package]] 425 + name = "mio" 426 + version = "1.2.0" 427 + source = "registry+https://github.com/rust-lang/crates.io-index" 428 + checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" 429 + dependencies = [ 430 + "libc", 431 + "wasi", 432 + "windows-sys 0.61.2", 433 + ] 434 + 435 + [[package]] 436 + name = "netstream" 437 + version = "0.1.0" 438 + dependencies = [ 439 + "libc", 440 + "once_cell", 441 + "reqwest", 442 + ] 443 + 444 + [[package]] 445 + name = "once_cell" 446 + version = "1.21.4" 447 + source = "registry+https://github.com/rust-lang/crates.io-index" 448 + checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" 449 + 450 + [[package]] 451 + name = "percent-encoding" 452 + version = "2.3.2" 453 + source = "registry+https://github.com/rust-lang/crates.io-index" 454 + checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 455 + 456 + [[package]] 457 + name = "pin-project-lite" 458 + version = "0.2.17" 459 + source = "registry+https://github.com/rust-lang/crates.io-index" 460 + checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" 461 + 462 + [[package]] 463 + name = "potential_utf" 464 + version = "0.1.5" 465 + source = "registry+https://github.com/rust-lang/crates.io-index" 466 + checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" 467 + dependencies = [ 468 + "zerovec", 469 + ] 470 + 471 + [[package]] 472 + name = "ppv-lite86" 473 + version = "0.2.21" 474 + source = "registry+https://github.com/rust-lang/crates.io-index" 475 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 476 + dependencies = [ 477 + "zerocopy", 478 + ] 479 + 480 + [[package]] 481 + name = "proc-macro2" 482 + version = "1.0.106" 483 + source = "registry+https://github.com/rust-lang/crates.io-index" 484 + checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" 485 + dependencies = [ 486 + "unicode-ident", 487 + ] 488 + 489 + [[package]] 490 + name = "quinn" 491 + version = "0.11.9" 492 + source = "registry+https://github.com/rust-lang/crates.io-index" 493 + checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" 494 + dependencies = [ 495 + "bytes", 496 + "cfg_aliases", 497 + "pin-project-lite", 498 + "quinn-proto", 499 + "quinn-udp", 500 + "rustc-hash", 501 + "rustls", 502 + "socket2", 503 + "thiserror", 504 + "tokio", 505 + "tracing", 506 + "web-time", 507 + ] 508 + 509 + [[package]] 510 + name = "quinn-proto" 511 + version = "0.11.14" 512 + source = "registry+https://github.com/rust-lang/crates.io-index" 513 + checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" 514 + dependencies = [ 515 + "bytes", 516 + "getrandom 0.3.4", 517 + "lru-slab", 518 + "rand", 519 + "ring", 520 + "rustc-hash", 521 + "rustls", 522 + "rustls-pki-types", 523 + "slab", 524 + "thiserror", 525 + "tinyvec", 526 + "tracing", 527 + "web-time", 528 + ] 529 + 530 + [[package]] 531 + name = "quinn-udp" 532 + version = "0.5.14" 533 + source = "registry+https://github.com/rust-lang/crates.io-index" 534 + checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" 535 + dependencies = [ 536 + "cfg_aliases", 537 + "libc", 538 + "once_cell", 539 + "socket2", 540 + "tracing", 541 + "windows-sys 0.60.2", 542 + ] 543 + 544 + [[package]] 545 + name = "quote" 546 + version = "1.0.45" 547 + source = "registry+https://github.com/rust-lang/crates.io-index" 548 + checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" 549 + dependencies = [ 550 + "proc-macro2", 551 + ] 552 + 553 + [[package]] 554 + name = "r-efi" 555 + version = "5.3.0" 556 + source = "registry+https://github.com/rust-lang/crates.io-index" 557 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 558 + 559 + [[package]] 560 + name = "rand" 561 + version = "0.9.4" 562 + source = "registry+https://github.com/rust-lang/crates.io-index" 563 + checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" 564 + dependencies = [ 565 + "rand_chacha", 566 + "rand_core", 567 + ] 568 + 569 + [[package]] 570 + name = "rand_chacha" 571 + version = "0.9.0" 572 + source = "registry+https://github.com/rust-lang/crates.io-index" 573 + checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 574 + dependencies = [ 575 + "ppv-lite86", 576 + "rand_core", 577 + ] 578 + 579 + [[package]] 580 + name = "rand_core" 581 + version = "0.9.5" 582 + source = "registry+https://github.com/rust-lang/crates.io-index" 583 + checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" 584 + dependencies = [ 585 + "getrandom 0.3.4", 586 + ] 587 + 588 + [[package]] 589 + name = "reqwest" 590 + version = "0.12.28" 591 + source = "registry+https://github.com/rust-lang/crates.io-index" 592 + checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" 593 + dependencies = [ 594 + "base64", 595 + "bytes", 596 + "futures-channel", 597 + "futures-core", 598 + "futures-util", 599 + "http", 600 + "http-body", 601 + "http-body-util", 602 + "hyper", 603 + "hyper-rustls", 604 + "hyper-util", 605 + "js-sys", 606 + "log", 607 + "percent-encoding", 608 + "pin-project-lite", 609 + "quinn", 610 + "rustls", 611 + "rustls-pki-types", 612 + "serde", 613 + "serde_json", 614 + "serde_urlencoded", 615 + "sync_wrapper", 616 + "tokio", 617 + "tokio-rustls", 618 + "tower", 619 + "tower-http", 620 + "tower-service", 621 + "url", 622 + "wasm-bindgen", 623 + "wasm-bindgen-futures", 624 + "web-sys", 625 + "webpki-roots", 626 + ] 627 + 628 + [[package]] 629 + name = "ring" 630 + version = "0.17.14" 631 + source = "registry+https://github.com/rust-lang/crates.io-index" 632 + checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 633 + dependencies = [ 634 + "cc", 635 + "cfg-if", 636 + "getrandom 0.2.17", 637 + "libc", 638 + "untrusted", 639 + "windows-sys 0.52.0", 640 + ] 641 + 642 + [[package]] 643 + name = "rustc-hash" 644 + version = "2.1.2" 645 + source = "registry+https://github.com/rust-lang/crates.io-index" 646 + checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" 647 + 648 + [[package]] 649 + name = "rustls" 650 + version = "0.23.38" 651 + source = "registry+https://github.com/rust-lang/crates.io-index" 652 + checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21" 653 + dependencies = [ 654 + "once_cell", 655 + "ring", 656 + "rustls-pki-types", 657 + "rustls-webpki", 658 + "subtle", 659 + "zeroize", 660 + ] 661 + 662 + [[package]] 663 + name = "rustls-pki-types" 664 + version = "1.14.0" 665 + source = "registry+https://github.com/rust-lang/crates.io-index" 666 + checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" 667 + dependencies = [ 668 + "web-time", 669 + "zeroize", 670 + ] 671 + 672 + [[package]] 673 + name = "rustls-webpki" 674 + version = "0.103.12" 675 + source = "registry+https://github.com/rust-lang/crates.io-index" 676 + checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" 677 + dependencies = [ 678 + "ring", 679 + "rustls-pki-types", 680 + "untrusted", 681 + ] 682 + 683 + [[package]] 684 + name = "rustversion" 685 + version = "1.0.22" 686 + source = "registry+https://github.com/rust-lang/crates.io-index" 687 + checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 688 + 689 + [[package]] 690 + name = "ryu" 691 + version = "1.0.23" 692 + source = "registry+https://github.com/rust-lang/crates.io-index" 693 + checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" 694 + 695 + [[package]] 696 + name = "serde" 697 + version = "1.0.228" 698 + source = "registry+https://github.com/rust-lang/crates.io-index" 699 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 700 + dependencies = [ 701 + "serde_core", 702 + "serde_derive", 703 + ] 704 + 705 + [[package]] 706 + name = "serde_core" 707 + version = "1.0.228" 708 + source = "registry+https://github.com/rust-lang/crates.io-index" 709 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 710 + dependencies = [ 711 + "serde_derive", 712 + ] 713 + 714 + [[package]] 715 + name = "serde_derive" 716 + version = "1.0.228" 717 + source = "registry+https://github.com/rust-lang/crates.io-index" 718 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 719 + dependencies = [ 720 + "proc-macro2", 721 + "quote", 722 + "syn", 723 + ] 724 + 725 + [[package]] 726 + name = "serde_json" 727 + version = "1.0.149" 728 + source = "registry+https://github.com/rust-lang/crates.io-index" 729 + checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" 730 + dependencies = [ 731 + "itoa", 732 + "memchr", 733 + "serde", 734 + "serde_core", 735 + "zmij", 736 + ] 737 + 738 + [[package]] 739 + name = "serde_urlencoded" 740 + version = "0.7.1" 741 + source = "registry+https://github.com/rust-lang/crates.io-index" 742 + checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 743 + dependencies = [ 744 + "form_urlencoded", 745 + "itoa", 746 + "ryu", 747 + "serde", 748 + ] 749 + 750 + [[package]] 751 + name = "shlex" 752 + version = "1.3.0" 753 + source = "registry+https://github.com/rust-lang/crates.io-index" 754 + checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 755 + 756 + [[package]] 757 + name = "slab" 758 + version = "0.4.12" 759 + source = "registry+https://github.com/rust-lang/crates.io-index" 760 + checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" 761 + 762 + [[package]] 763 + name = "smallvec" 764 + version = "1.15.1" 765 + source = "registry+https://github.com/rust-lang/crates.io-index" 766 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 767 + 768 + [[package]] 769 + name = "socket2" 770 + version = "0.6.3" 771 + source = "registry+https://github.com/rust-lang/crates.io-index" 772 + checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" 773 + dependencies = [ 774 + "libc", 775 + "windows-sys 0.61.2", 776 + ] 777 + 778 + [[package]] 779 + name = "stable_deref_trait" 780 + version = "1.2.1" 781 + source = "registry+https://github.com/rust-lang/crates.io-index" 782 + checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 783 + 784 + [[package]] 785 + name = "subtle" 786 + version = "2.6.1" 787 + source = "registry+https://github.com/rust-lang/crates.io-index" 788 + checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 789 + 790 + [[package]] 791 + name = "syn" 792 + version = "2.0.117" 793 + source = "registry+https://github.com/rust-lang/crates.io-index" 794 + checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" 795 + dependencies = [ 796 + "proc-macro2", 797 + "quote", 798 + "unicode-ident", 799 + ] 800 + 801 + [[package]] 802 + name = "sync_wrapper" 803 + version = "1.0.2" 804 + source = "registry+https://github.com/rust-lang/crates.io-index" 805 + checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 806 + dependencies = [ 807 + "futures-core", 808 + ] 809 + 810 + [[package]] 811 + name = "synstructure" 812 + version = "0.13.2" 813 + source = "registry+https://github.com/rust-lang/crates.io-index" 814 + checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 815 + dependencies = [ 816 + "proc-macro2", 817 + "quote", 818 + "syn", 819 + ] 820 + 821 + [[package]] 822 + name = "thiserror" 823 + version = "2.0.18" 824 + source = "registry+https://github.com/rust-lang/crates.io-index" 825 + checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" 826 + dependencies = [ 827 + "thiserror-impl", 828 + ] 829 + 830 + [[package]] 831 + name = "thiserror-impl" 832 + version = "2.0.18" 833 + source = "registry+https://github.com/rust-lang/crates.io-index" 834 + checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" 835 + dependencies = [ 836 + "proc-macro2", 837 + "quote", 838 + "syn", 839 + ] 840 + 841 + [[package]] 842 + name = "tinystr" 843 + version = "0.8.3" 844 + source = "registry+https://github.com/rust-lang/crates.io-index" 845 + checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" 846 + dependencies = [ 847 + "displaydoc", 848 + "zerovec", 849 + ] 850 + 851 + [[package]] 852 + name = "tinyvec" 853 + version = "1.11.0" 854 + source = "registry+https://github.com/rust-lang/crates.io-index" 855 + checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" 856 + dependencies = [ 857 + "tinyvec_macros", 858 + ] 859 + 860 + [[package]] 861 + name = "tinyvec_macros" 862 + version = "0.1.1" 863 + source = "registry+https://github.com/rust-lang/crates.io-index" 864 + checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 865 + 866 + [[package]] 867 + name = "tokio" 868 + version = "1.51.1" 869 + source = "registry+https://github.com/rust-lang/crates.io-index" 870 + checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" 871 + dependencies = [ 872 + "bytes", 873 + "libc", 874 + "mio", 875 + "pin-project-lite", 876 + "socket2", 877 + "windows-sys 0.61.2", 878 + ] 879 + 880 + [[package]] 881 + name = "tokio-rustls" 882 + version = "0.26.4" 883 + source = "registry+https://github.com/rust-lang/crates.io-index" 884 + checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" 885 + dependencies = [ 886 + "rustls", 887 + "tokio", 888 + ] 889 + 890 + [[package]] 891 + name = "tower" 892 + version = "0.5.3" 893 + source = "registry+https://github.com/rust-lang/crates.io-index" 894 + checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" 895 + dependencies = [ 896 + "futures-core", 897 + "futures-util", 898 + "pin-project-lite", 899 + "sync_wrapper", 900 + "tokio", 901 + "tower-layer", 902 + "tower-service", 903 + ] 904 + 905 + [[package]] 906 + name = "tower-http" 907 + version = "0.6.8" 908 + source = "registry+https://github.com/rust-lang/crates.io-index" 909 + checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" 910 + dependencies = [ 911 + "bitflags", 912 + "bytes", 913 + "futures-util", 914 + "http", 915 + "http-body", 916 + "iri-string", 917 + "pin-project-lite", 918 + "tower", 919 + "tower-layer", 920 + "tower-service", 921 + ] 922 + 923 + [[package]] 924 + name = "tower-layer" 925 + version = "0.3.3" 926 + source = "registry+https://github.com/rust-lang/crates.io-index" 927 + checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 928 + 929 + [[package]] 930 + name = "tower-service" 931 + version = "0.3.3" 932 + source = "registry+https://github.com/rust-lang/crates.io-index" 933 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 934 + 935 + [[package]] 936 + name = "tracing" 937 + version = "0.1.44" 938 + source = "registry+https://github.com/rust-lang/crates.io-index" 939 + checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" 940 + dependencies = [ 941 + "pin-project-lite", 942 + "tracing-core", 943 + ] 944 + 945 + [[package]] 946 + name = "tracing-core" 947 + version = "0.1.36" 948 + source = "registry+https://github.com/rust-lang/crates.io-index" 949 + checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" 950 + dependencies = [ 951 + "once_cell", 952 + ] 953 + 954 + [[package]] 955 + name = "try-lock" 956 + version = "0.2.5" 957 + source = "registry+https://github.com/rust-lang/crates.io-index" 958 + checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 959 + 960 + [[package]] 961 + name = "unicode-ident" 962 + version = "1.0.24" 963 + source = "registry+https://github.com/rust-lang/crates.io-index" 964 + checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" 965 + 966 + [[package]] 967 + name = "untrusted" 968 + version = "0.9.0" 969 + source = "registry+https://github.com/rust-lang/crates.io-index" 970 + checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 971 + 972 + [[package]] 973 + name = "url" 974 + version = "2.5.8" 975 + source = "registry+https://github.com/rust-lang/crates.io-index" 976 + checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" 977 + dependencies = [ 978 + "form_urlencoded", 979 + "idna", 980 + "percent-encoding", 981 + "serde", 982 + ] 983 + 984 + [[package]] 985 + name = "utf8_iter" 986 + version = "1.0.4" 987 + source = "registry+https://github.com/rust-lang/crates.io-index" 988 + checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 989 + 990 + [[package]] 991 + name = "want" 992 + version = "0.3.1" 993 + source = "registry+https://github.com/rust-lang/crates.io-index" 994 + checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 995 + dependencies = [ 996 + "try-lock", 997 + ] 998 + 999 + [[package]] 1000 + name = "wasi" 1001 + version = "0.11.1+wasi-snapshot-preview1" 1002 + source = "registry+https://github.com/rust-lang/crates.io-index" 1003 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 1004 + 1005 + [[package]] 1006 + name = "wasip2" 1007 + version = "1.0.2+wasi-0.2.9" 1008 + source = "registry+https://github.com/rust-lang/crates.io-index" 1009 + checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" 1010 + dependencies = [ 1011 + "wit-bindgen", 1012 + ] 1013 + 1014 + [[package]] 1015 + name = "wasm-bindgen" 1016 + version = "0.2.118" 1017 + source = "registry+https://github.com/rust-lang/crates.io-index" 1018 + checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" 1019 + dependencies = [ 1020 + "cfg-if", 1021 + "once_cell", 1022 + "rustversion", 1023 + "wasm-bindgen-macro", 1024 + "wasm-bindgen-shared", 1025 + ] 1026 + 1027 + [[package]] 1028 + name = "wasm-bindgen-futures" 1029 + version = "0.4.68" 1030 + source = "registry+https://github.com/rust-lang/crates.io-index" 1031 + checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" 1032 + dependencies = [ 1033 + "js-sys", 1034 + "wasm-bindgen", 1035 + ] 1036 + 1037 + [[package]] 1038 + name = "wasm-bindgen-macro" 1039 + version = "0.2.118" 1040 + source = "registry+https://github.com/rust-lang/crates.io-index" 1041 + checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" 1042 + dependencies = [ 1043 + "quote", 1044 + "wasm-bindgen-macro-support", 1045 + ] 1046 + 1047 + [[package]] 1048 + name = "wasm-bindgen-macro-support" 1049 + version = "0.2.118" 1050 + source = "registry+https://github.com/rust-lang/crates.io-index" 1051 + checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" 1052 + dependencies = [ 1053 + "bumpalo", 1054 + "proc-macro2", 1055 + "quote", 1056 + "syn", 1057 + "wasm-bindgen-shared", 1058 + ] 1059 + 1060 + [[package]] 1061 + name = "wasm-bindgen-shared" 1062 + version = "0.2.118" 1063 + source = "registry+https://github.com/rust-lang/crates.io-index" 1064 + checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" 1065 + dependencies = [ 1066 + "unicode-ident", 1067 + ] 1068 + 1069 + [[package]] 1070 + name = "web-sys" 1071 + version = "0.3.95" 1072 + source = "registry+https://github.com/rust-lang/crates.io-index" 1073 + checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" 1074 + dependencies = [ 1075 + "js-sys", 1076 + "wasm-bindgen", 1077 + ] 1078 + 1079 + [[package]] 1080 + name = "web-time" 1081 + version = "1.1.0" 1082 + source = "registry+https://github.com/rust-lang/crates.io-index" 1083 + checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1084 + dependencies = [ 1085 + "js-sys", 1086 + "wasm-bindgen", 1087 + ] 1088 + 1089 + [[package]] 1090 + name = "webpki-roots" 1091 + version = "1.0.6" 1092 + source = "registry+https://github.com/rust-lang/crates.io-index" 1093 + checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" 1094 + dependencies = [ 1095 + "rustls-pki-types", 1096 + ] 1097 + 1098 + [[package]] 1099 + name = "windows-link" 1100 + version = "0.2.1" 1101 + source = "registry+https://github.com/rust-lang/crates.io-index" 1102 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 1103 + 1104 + [[package]] 1105 + name = "windows-sys" 1106 + version = "0.52.0" 1107 + source = "registry+https://github.com/rust-lang/crates.io-index" 1108 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1109 + dependencies = [ 1110 + "windows-targets 0.52.6", 1111 + ] 1112 + 1113 + [[package]] 1114 + name = "windows-sys" 1115 + version = "0.60.2" 1116 + source = "registry+https://github.com/rust-lang/crates.io-index" 1117 + checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 1118 + dependencies = [ 1119 + "windows-targets 0.53.5", 1120 + ] 1121 + 1122 + [[package]] 1123 + name = "windows-sys" 1124 + version = "0.61.2" 1125 + source = "registry+https://github.com/rust-lang/crates.io-index" 1126 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 1127 + dependencies = [ 1128 + "windows-link", 1129 + ] 1130 + 1131 + [[package]] 1132 + name = "windows-targets" 1133 + version = "0.52.6" 1134 + source = "registry+https://github.com/rust-lang/crates.io-index" 1135 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1136 + dependencies = [ 1137 + "windows_aarch64_gnullvm 0.52.6", 1138 + "windows_aarch64_msvc 0.52.6", 1139 + "windows_i686_gnu 0.52.6", 1140 + "windows_i686_gnullvm 0.52.6", 1141 + "windows_i686_msvc 0.52.6", 1142 + "windows_x86_64_gnu 0.52.6", 1143 + "windows_x86_64_gnullvm 0.52.6", 1144 + "windows_x86_64_msvc 0.52.6", 1145 + ] 1146 + 1147 + [[package]] 1148 + name = "windows-targets" 1149 + version = "0.53.5" 1150 + source = "registry+https://github.com/rust-lang/crates.io-index" 1151 + checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" 1152 + dependencies = [ 1153 + "windows-link", 1154 + "windows_aarch64_gnullvm 0.53.1", 1155 + "windows_aarch64_msvc 0.53.1", 1156 + "windows_i686_gnu 0.53.1", 1157 + "windows_i686_gnullvm 0.53.1", 1158 + "windows_i686_msvc 0.53.1", 1159 + "windows_x86_64_gnu 0.53.1", 1160 + "windows_x86_64_gnullvm 0.53.1", 1161 + "windows_x86_64_msvc 0.53.1", 1162 + ] 1163 + 1164 + [[package]] 1165 + name = "windows_aarch64_gnullvm" 1166 + version = "0.52.6" 1167 + source = "registry+https://github.com/rust-lang/crates.io-index" 1168 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1169 + 1170 + [[package]] 1171 + name = "windows_aarch64_gnullvm" 1172 + version = "0.53.1" 1173 + source = "registry+https://github.com/rust-lang/crates.io-index" 1174 + checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" 1175 + 1176 + [[package]] 1177 + name = "windows_aarch64_msvc" 1178 + version = "0.52.6" 1179 + source = "registry+https://github.com/rust-lang/crates.io-index" 1180 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1181 + 1182 + [[package]] 1183 + name = "windows_aarch64_msvc" 1184 + version = "0.53.1" 1185 + source = "registry+https://github.com/rust-lang/crates.io-index" 1186 + checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" 1187 + 1188 + [[package]] 1189 + name = "windows_i686_gnu" 1190 + version = "0.52.6" 1191 + source = "registry+https://github.com/rust-lang/crates.io-index" 1192 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1193 + 1194 + [[package]] 1195 + name = "windows_i686_gnu" 1196 + version = "0.53.1" 1197 + source = "registry+https://github.com/rust-lang/crates.io-index" 1198 + checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" 1199 + 1200 + [[package]] 1201 + name = "windows_i686_gnullvm" 1202 + version = "0.52.6" 1203 + source = "registry+https://github.com/rust-lang/crates.io-index" 1204 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1205 + 1206 + [[package]] 1207 + name = "windows_i686_gnullvm" 1208 + version = "0.53.1" 1209 + source = "registry+https://github.com/rust-lang/crates.io-index" 1210 + checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" 1211 + 1212 + [[package]] 1213 + name = "windows_i686_msvc" 1214 + version = "0.52.6" 1215 + source = "registry+https://github.com/rust-lang/crates.io-index" 1216 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1217 + 1218 + [[package]] 1219 + name = "windows_i686_msvc" 1220 + version = "0.53.1" 1221 + source = "registry+https://github.com/rust-lang/crates.io-index" 1222 + checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" 1223 + 1224 + [[package]] 1225 + name = "windows_x86_64_gnu" 1226 + version = "0.52.6" 1227 + source = "registry+https://github.com/rust-lang/crates.io-index" 1228 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1229 + 1230 + [[package]] 1231 + name = "windows_x86_64_gnu" 1232 + version = "0.53.1" 1233 + source = "registry+https://github.com/rust-lang/crates.io-index" 1234 + checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" 1235 + 1236 + [[package]] 1237 + name = "windows_x86_64_gnullvm" 1238 + version = "0.52.6" 1239 + source = "registry+https://github.com/rust-lang/crates.io-index" 1240 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1241 + 1242 + [[package]] 1243 + name = "windows_x86_64_gnullvm" 1244 + version = "0.53.1" 1245 + source = "registry+https://github.com/rust-lang/crates.io-index" 1246 + checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" 1247 + 1248 + [[package]] 1249 + name = "windows_x86_64_msvc" 1250 + version = "0.52.6" 1251 + source = "registry+https://github.com/rust-lang/crates.io-index" 1252 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1253 + 1254 + [[package]] 1255 + name = "windows_x86_64_msvc" 1256 + version = "0.53.1" 1257 + source = "registry+https://github.com/rust-lang/crates.io-index" 1258 + checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" 1259 + 1260 + [[package]] 1261 + name = "wit-bindgen" 1262 + version = "0.51.0" 1263 + source = "registry+https://github.com/rust-lang/crates.io-index" 1264 + checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" 1265 + 1266 + [[package]] 1267 + name = "writeable" 1268 + version = "0.6.3" 1269 + source = "registry+https://github.com/rust-lang/crates.io-index" 1270 + checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" 1271 + 1272 + [[package]] 1273 + name = "yoke" 1274 + version = "0.8.2" 1275 + source = "registry+https://github.com/rust-lang/crates.io-index" 1276 + checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" 1277 + dependencies = [ 1278 + "stable_deref_trait", 1279 + "yoke-derive", 1280 + "zerofrom", 1281 + ] 1282 + 1283 + [[package]] 1284 + name = "yoke-derive" 1285 + version = "0.8.2" 1286 + source = "registry+https://github.com/rust-lang/crates.io-index" 1287 + checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" 1288 + dependencies = [ 1289 + "proc-macro2", 1290 + "quote", 1291 + "syn", 1292 + "synstructure", 1293 + ] 1294 + 1295 + [[package]] 1296 + name = "zerocopy" 1297 + version = "0.8.48" 1298 + source = "registry+https://github.com/rust-lang/crates.io-index" 1299 + checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" 1300 + dependencies = [ 1301 + "zerocopy-derive", 1302 + ] 1303 + 1304 + [[package]] 1305 + name = "zerocopy-derive" 1306 + version = "0.8.48" 1307 + source = "registry+https://github.com/rust-lang/crates.io-index" 1308 + checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" 1309 + dependencies = [ 1310 + "proc-macro2", 1311 + "quote", 1312 + "syn", 1313 + ] 1314 + 1315 + [[package]] 1316 + name = "zerofrom" 1317 + version = "0.1.7" 1318 + source = "registry+https://github.com/rust-lang/crates.io-index" 1319 + checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" 1320 + dependencies = [ 1321 + "zerofrom-derive", 1322 + ] 1323 + 1324 + [[package]] 1325 + name = "zerofrom-derive" 1326 + version = "0.1.7" 1327 + source = "registry+https://github.com/rust-lang/crates.io-index" 1328 + checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" 1329 + dependencies = [ 1330 + "proc-macro2", 1331 + "quote", 1332 + "syn", 1333 + "synstructure", 1334 + ] 1335 + 1336 + [[package]] 1337 + name = "zeroize" 1338 + version = "1.8.2" 1339 + source = "registry+https://github.com/rust-lang/crates.io-index" 1340 + checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" 1341 + 1342 + [[package]] 1343 + name = "zerotrie" 1344 + version = "0.2.4" 1345 + source = "registry+https://github.com/rust-lang/crates.io-index" 1346 + checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" 1347 + dependencies = [ 1348 + "displaydoc", 1349 + "yoke", 1350 + "zerofrom", 1351 + ] 1352 + 1353 + [[package]] 1354 + name = "zerovec" 1355 + version = "0.11.6" 1356 + source = "registry+https://github.com/rust-lang/crates.io-index" 1357 + checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" 1358 + dependencies = [ 1359 + "yoke", 1360 + "zerofrom", 1361 + "zerovec-derive", 1362 + ] 1363 + 1364 + [[package]] 1365 + name = "zerovec-derive" 1366 + version = "0.11.3" 1367 + source = "registry+https://github.com/rust-lang/crates.io-index" 1368 + checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" 1369 + dependencies = [ 1370 + "proc-macro2", 1371 + "quote", 1372 + "syn", 1373 + ] 1374 + 1375 + [[package]] 1376 + name = "zmij" 1377 + version = "1.0.21" 1378 + source = "registry+https://github.com/rust-lang/crates.io-index" 1379 + checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+16
crates/netstream/Cargo.toml
··· 1 + [workspace] 2 + members = ["."] 3 + 4 + [package] 5 + name = "netstream" 6 + version = "0.1.0" 7 + edition = "2021" 8 + 9 + [lib] 10 + name = "rbnetstream" 11 + crate-type = ["staticlib"] 12 + 13 + [dependencies] 14 + reqwest = { version = "0.12.5", features = ["blocking", "rustls-tls"], default-features = false } 15 + once_cell = "1.17.1" 16 + libc = "0.2.168"
+220
crates/netstream/src/lib.rs
··· 1 + use once_cell::sync::Lazy; 2 + use std::collections::HashMap; 3 + use std::ffi::CStr; 4 + use std::io::Read; 5 + use std::os::raw::c_char; 6 + use std::sync::atomic::{AtomicI32, Ordering}; 7 + use std::sync::Mutex; 8 + 9 + /// Sentinel handle ID returned on error. 10 + const INVALID_HANDLE: i32 = -1; 11 + 12 + /// Per-stream state. 13 + struct StreamState { 14 + url: String, 15 + pos: u64, 16 + content_length: Option<u64>, 17 + response: Option<reqwest::blocking::Response>, 18 + client: reqwest::blocking::Client, 19 + } 20 + 21 + impl StreamState { 22 + fn new(url: String, client: reqwest::blocking::Client) -> Option<Self> { 23 + let response = client.get(&url).send().ok()?; 24 + if !response.status().is_success() { 25 + return None; 26 + } 27 + let content_length = response.content_length(); 28 + Some(StreamState { 29 + url, 30 + pos: 0, 31 + content_length, 32 + response: Some(response), 33 + client, 34 + }) 35 + } 36 + 37 + /// Re-issue the request starting at `new_pos` using an HTTP Range header. 38 + /// Returns `true` on success, `false` if the server doesn't support Range 39 + /// or if the request fails. 40 + fn seek_to(&mut self, new_pos: u64) -> bool { 41 + self.response = None; 42 + let result = self 43 + .client 44 + .get(&self.url) 45 + .header("Range", format!("bytes={}-", new_pos)) 46 + .send(); 47 + 48 + match result { 49 + Ok(resp) 50 + if resp.status().is_success() || resp.status().as_u16() == 206 => 51 + { 52 + // Try to extract total length from Content-Range if not yet known. 53 + if self.content_length.is_none() { 54 + if let Some(cr) = resp.headers().get("content-range") { 55 + if let Ok(cr_str) = cr.to_str() { 56 + // Format: "bytes START-END/TOTAL" 57 + if let Some(total_str) = cr_str.split('/').last() { 58 + if let Ok(total) = total_str.trim().parse::<u64>() { 59 + self.content_length = Some(total); 60 + } 61 + } 62 + } 63 + } 64 + } 65 + self.response = Some(resp); 66 + self.pos = new_pos; 67 + true 68 + } 69 + _ => false, 70 + } 71 + } 72 + } 73 + 74 + static STREAMS: Lazy<Mutex<HashMap<i32, StreamState>>> = 75 + Lazy::new(|| Mutex::new(HashMap::new())); 76 + 77 + static NEXT_HANDLE: AtomicI32 = AtomicI32::new(0); 78 + 79 + // ------------------------------------------------------------------ 80 + // Public C ABI 81 + // ------------------------------------------------------------------ 82 + 83 + /// Open a URL and return an integer handle, or -1 on failure. 84 + /// 85 + /// # Safety 86 + /// `url` must be a valid, NUL-terminated C string. 87 + #[no_mangle] 88 + pub unsafe extern "C" fn rb_net_open(url: *const c_char) -> i32 { 89 + if url.is_null() { 90 + return INVALID_HANDLE; 91 + } 92 + let url_str = match CStr::from_ptr(url).to_str() { 93 + Ok(s) => s.to_owned(), 94 + Err(_) => return INVALID_HANDLE, 95 + }; 96 + 97 + let client = match reqwest::blocking::Client::builder() 98 + .use_rustls_tls() 99 + .build() 100 + { 101 + Ok(c) => c, 102 + Err(_) => return INVALID_HANDLE, 103 + }; 104 + 105 + let state = match StreamState::new(url_str, client) { 106 + Some(s) => s, 107 + None => return INVALID_HANDLE, 108 + }; 109 + 110 + let handle = NEXT_HANDLE.fetch_add(1, Ordering::SeqCst); 111 + STREAMS.lock().unwrap().insert(handle, state); 112 + handle 113 + } 114 + 115 + /// Read up to `n` bytes from stream `h` into `dst`. 116 + /// Returns the number of bytes read, 0 on EOF, or -1 on error. 117 + /// 118 + /// # Safety 119 + /// `dst` must point to a buffer of at least `n` bytes. 120 + #[no_mangle] 121 + pub unsafe extern "C" fn rb_net_read(h: i32, dst: *mut libc::c_void, n: libc::size_t) -> i64 { 122 + if dst.is_null() || n == 0 { 123 + return 0; 124 + } 125 + let mut streams = STREAMS.lock().unwrap(); 126 + let state = match streams.get_mut(&h) { 127 + Some(s) => s, 128 + None => return -1, 129 + }; 130 + let resp = match &mut state.response { 131 + Some(r) => r, 132 + None => return -1, 133 + }; 134 + let buf = std::slice::from_raw_parts_mut(dst as *mut u8, n); 135 + match resp.read(buf) { 136 + Ok(bytes_read) => { 137 + state.pos += bytes_read as u64; 138 + bytes_read as i64 139 + } 140 + Err(_) => -1, 141 + } 142 + } 143 + 144 + /// Seek within stream `h`. `whence` follows POSIX semantics: 145 + /// 0 = SEEK_SET, 1 = SEEK_CUR, 2 = SEEK_END. 146 + /// Returns the new position on success, or -1 on failure. 147 + #[no_mangle] 148 + pub extern "C" fn rb_net_lseek(h: i32, off: i64, whence: libc::c_int) -> i64 { 149 + const SEEK_SET: libc::c_int = 0; 150 + const SEEK_CUR: libc::c_int = 1; 151 + const SEEK_END: libc::c_int = 2; 152 + 153 + let mut streams = STREAMS.lock().unwrap(); 154 + let state = match streams.get_mut(&h) { 155 + Some(s) => s, 156 + None => return -1, 157 + }; 158 + 159 + let new_pos: u64 = match whence { 160 + x if x == SEEK_SET => { 161 + if off < 0 { 162 + return -1; 163 + } 164 + off as u64 165 + } 166 + x if x == SEEK_CUR => { 167 + if off < 0 { 168 + let abs_off = (-off) as u64; 169 + if abs_off > state.pos { 170 + return -1; 171 + } 172 + state.pos - abs_off 173 + } else { 174 + state.pos + off as u64 175 + } 176 + } 177 + x if x == SEEK_END => { 178 + let len = match state.content_length { 179 + Some(l) => l, 180 + None => return -1, 181 + }; 182 + if off > 0 { 183 + return -1; 184 + } 185 + let abs_off = (-off) as u64; 186 + if abs_off > len { 187 + return -1; 188 + } 189 + len - abs_off 190 + } 191 + _ => return -1, 192 + }; 193 + 194 + // Fast-path: already there (no need to restart the request). 195 + if new_pos == state.pos { 196 + return state.pos as i64; 197 + } 198 + 199 + if state.seek_to(new_pos) { 200 + state.pos as i64 201 + } else { 202 + -1 203 + } 204 + } 205 + 206 + /// Return the total content length of stream `h`, or -1 if unknown. 207 + #[no_mangle] 208 + pub extern "C" fn rb_net_len(h: i32) -> i64 { 209 + let streams = STREAMS.lock().unwrap(); 210 + match streams.get(&h) { 211 + Some(state) => state.content_length.map(|l| l as i64).unwrap_or(-1), 212 + None => -1, 213 + } 214 + } 215 + 216 + /// Close stream `h` and release its resources. 217 + #[no_mangle] 218 + pub extern "C" fn rb_net_close(h: i32) { 219 + STREAMS.lock().unwrap().remove(&h); 220 + }
+38 -2
docs/UISIMULATOR
··· 38 38 directory, create subdirectories and do all sorts of things you want to be 39 39 able to browse when you fire up the simulator. 40 40 41 + Rust toolchain (edition 2021) and Cargo must be installed to build the 42 + network-stream support library (crates/netstream). The build will run 43 + `cargo build --manifest-path crates/netstream/Cargo.toml --release` 44 + automatically during `make`. 45 + 41 46 3. Run Uisimulator 42 47 43 48 To create a simulated disk drive for the simulator to see, create a ··· 46 51 47 52 Run 'rockboxui'. 48 53 49 - 4. Target Keypad Equivalents 54 + 4. Network Stream Playback (HTTP/HTTPS URLs) 55 + 56 + The SDL simulator supports playing audio directly from HTTP and HTTPS URLs. 57 + URLs are treated exactly like local file paths everywhere in the UI (file 58 + browser, playlists, etc.). 59 + 60 + To play a URL: 61 + 62 + a) Playlist method (recommended): 63 + Create a plain-text .m3u or .m3u8 playlist file inside your simdisk, 64 + with one URL per line, e.g.: 65 + 66 + simdisk/streams.m3u 67 + ---------------------- 68 + https://example.com/track1.mp3 69 + https://example.com/track2.ogg 70 + 71 + Load the playlist from the file browser and press Play. 72 + 73 + b) Direct entry (if the target UI supports text input for file paths): 74 + Enter the full URL including scheme, e.g.: 75 + https://example.com/audio/song.mp3 76 + 77 + Requirements: 78 + * The server must serve the file with a correct Content-Type header for 79 + the codec to be selected automatically. 80 + * Seeking works for servers that support HTTP Range requests (RFC 7233). 81 + For servers that do not support Range requests, seeking will fail 82 + gracefully and playback continues from the current position. 83 + * HTTPS is supported via rustls (no system CA store dependency). 84 + 85 + 5. Target Keypad Equivalents 50 86 51 87 The keyboard's numerical keypad is used to simulate the target keypad. See 52 88 the output rockboxui displays on start for details. 53 89 54 - 5. Mouse Input 90 + 6. Mouse Input 55 91 56 92 Clicking on the button images on the background will simulate pressing the 57 93 appropriate buttons. On scroll wheel targts the mouse wheel will simulate
+18 -3
uisimulator/uisimulator.make
··· 24 24 UIBMP=$(BUILDDIR)/UI256.bmp 25 25 endif 26 26 27 + # Rust network-stream static library (built from crates/netstream). 28 + NETSTREAM_LIB = $(BUILDDIR)/librbnetstream.a 29 + NETSTREAM_MANIFEST = $(ROOTDIR)/crates/netstream/Cargo.toml 30 + NETSTREAM_CARGO_LIB = $(ROOTDIR)/crates/netstream/target/release/librbnetstream.a 31 + 32 + .PHONY: netstream-lib 33 + netstream-lib: 34 + cargo build --manifest-path $(NETSTREAM_MANIFEST) --release 35 + 36 + $(NETSTREAM_CARGO_LIB): netstream-lib 37 + 38 + $(NETSTREAM_LIB): $(NETSTREAM_CARGO_LIB) 39 + $(call PRINTS,CP librbnetstream.a)cp $< $@ 40 + 27 41 .SECONDEXPANSION: # $$(OBJ) is not populated until after this 28 42 29 43 $(SIMLIB): $$(SIMOBJ) $(UIBMP) 30 44 $(SILENT)$(shell rm -f $@) 31 45 $(call PRINTS,AR $(@F))$(AR) rcs $@ $(SIMOBJ) >/dev/null 32 46 33 - $(BUILDDIR)/$(BINARY): $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) $(SIMLIB) 47 + $(BUILDDIR)/$(BINARY): $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) $(SIMLIB) $(NETSTREAM_LIB) 34 48 ifeq ($(UNAME), Darwin) 35 - $(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,$(LDMAP_OPT),$(BUILDDIR)/rockbox.map 49 + $(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(LDOPTS) $(GLOBAL_LDOPTS) -lpthread -ldl \ 50 + -Wl,$(LDMAP_OPT),$(BUILDDIR)/rockbox.map 36 51 else 37 52 $(call PRINTS,LD $(BINARY))$(CC) -o $@ -Wl,--start-group $^ -Wl,--end-group $(LDOPTS) $(GLOBAL_LDOPTS) \ 38 - -Wl,$(LDMAP_OPT),$(BUILDDIR)/rockbox.map 53 + -lpthread -ldl -Wl,$(LDMAP_OPT),$(BUILDDIR)/rockbox.map 39 54 endif 40 55 $(SILENT)$(call objcopy,$@,$@) 41 56