├── .gitignore ├── .idea └── vcs.xml ├── LICENSE ├── README.md ├── build.gradle.kts ├── design └── BUFFER.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kotlin-js-store └── yarn.lock ├── settings.gradle.kts └── src ├── commonMain └── kotlin │ └── io │ └── ktor │ └── io │ ├── BitOperations.kt │ ├── Buffer.kt │ ├── BufferOperations.kt │ ├── BufferedBytesDestination.kt │ ├── BufferedBytesSource.kt │ ├── ByteArrayBuffer.kt │ ├── ByteArrayBufferPool.kt │ ├── ByteArrayOperations.kt │ ├── ByteOperations.kt │ ├── BytesDestination.kt │ ├── BytesSource.kt │ ├── Closeable.kt │ ├── DefaultPool.kt │ ├── Errors.kt │ ├── NoPoolImpl.kt │ └── Pool.kt ├── commonTest └── kotlin │ └── io │ └── ktor │ └── io │ ├── BufferTest.kt │ ├── BufferedBytesDestinationTest.kt │ ├── BufferedBytesSourceTest.kt │ ├── ByteArrayBufferTest.kt │ ├── TestBytesSource.kt │ └── utils │ ├── TestBytesDestination.kt │ └── testSuspend.kt ├── jsMain └── kotlin │ └── io │ └── ktor │ └── io │ ├── CloseableJs.kt │ ├── DefaultPool.kt │ └── IOExceptionJs.kt ├── jsTest └── kotlin │ └── io │ └── ktor │ └── io │ └── utils │ └── TestUtilsJs.kt ├── jvmMain └── kotlin │ └── io │ └── ktor │ └── io │ ├── CloseableJvm.kt │ ├── DefaultPool.kt │ ├── DirectByteBufferPool.kt │ ├── FileBytesDestination.kt │ ├── FileBytesSource.kt │ ├── IOExceptionJvm.kt │ ├── JvmBuffer.kt │ └── JvmBufferPool.kt ├── jvmTest └── kotlin │ └── io │ └── ktor │ └── io │ ├── FilesTest.kt │ ├── JvmBufferTest.kt │ └── utils │ └── TestUtilsJvm.kt ├── nativeMain └── kotlin │ └── io │ └── ktor │ └── io │ ├── Closeable.native.kt │ ├── DefaultPool.native.kt │ └── IOException.native.kt └── nativeTest └── kotlin └── io └── ktor └── io └── utils └── TestUtilsNative.kt /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .gradle 3 | .gradletasknamecache 4 | .idea/* 5 | !.idea/runConfigurations 6 | !.idea/runConfigurations/* 7 | !.idea/vcs.xml 8 | !.idea/dictionaries 9 | !.idea/dictionaries/* 10 | !.idea/copyright 11 | !.idea/copyright/* 12 | !.idea/codeStyles 13 | !.idea/codeStyles/* 14 | !.idea/icon.png 15 | out 16 | *.iml 17 | .vscode 18 | 19 | *.versionsBackup 20 | *.releaseBackup 21 | release.properties 22 | local.properties 23 | *.swp 24 | 25 | .video 26 | .attach_pid* 27 | apidoc 28 | 29 | bin/ 30 | .settings 31 | .project 32 | .classpath 33 | .konan 34 | 35 | .DS_Store 36 | 37 | hs_err_pid*.log 38 | 39 | gradle-user-home 40 | 41 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ktor IO 2 | 3 | Collection of IO primitives to work with network and files written in Kotlin using kotlinx.coroutines library 4 | 5 | ## Design Process 6 | 7 | Please note, current version of this library is not finished yet. We do not provide any guarantees that it will keep any 8 | backward compatibility. To get a motivation why things are implemented as it is, please see the [design](design) 9 | folder. 10 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2020 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. 3 | */ 4 | 5 | import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget 6 | 7 | buildscript { 8 | repositories { 9 | mavenLocal() 10 | mavenCentral() 11 | google() 12 | gradlePluginPortal() 13 | maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") 14 | } 15 | 16 | val kotlin_version: String by extra 17 | val atomicfu_version: String by extra 18 | 19 | dependencies { 20 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") 21 | classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version") 22 | } 23 | } 24 | 25 | plugins { 26 | kotlin("multiplatform") version "1.6.20" 27 | id("org.jetbrains.kotlinx.kover") version "0.5.0" 28 | `maven-publish` 29 | } 30 | 31 | group = "io.ktor" 32 | 33 | repositories { 34 | mavenLocal() 35 | mavenCentral() 36 | maven(url = "https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") 37 | maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") 38 | } 39 | 40 | apply(plugin = "kotlin-multiplatform") 41 | apply(plugin = "kotlinx-atomicfu") 42 | 43 | val coroutines_version: String by extra 44 | 45 | kotlin { 46 | jvm { 47 | compilations.all { 48 | kotlinOptions.jvmTarget = "1.8" 49 | } 50 | testRuns["test"].executionTask.configure { 51 | useJUnitPlatform() 52 | } 53 | } 54 | js(IR) { 55 | browser() 56 | nodejs() 57 | } 58 | 59 | val platforms: List = listOf( 60 | mingwX64(), 61 | linuxX64(), 62 | macosX64(), 63 | macosArm64(), 64 | iosX64(), 65 | iosArm64(), 66 | iosArm32(), 67 | iosSimulatorArm64(), 68 | watchosX86(), 69 | watchosX64(), 70 | watchosArm32(), 71 | watchosArm64(), 72 | watchosSimulatorArm64(), 73 | tvosX64(), 74 | tvosArm64(), 75 | tvosSimulatorArm64() 76 | ) 77 | 78 | explicitApi() 79 | 80 | sourceSets { 81 | val commonMain by getting { 82 | dependencies { 83 | } 84 | } 85 | val commonTest by getting { 86 | dependencies { 87 | api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") 88 | implementation(kotlin("test")) 89 | } 90 | } 91 | 92 | val nativeMain by creating 93 | val nativeTest by creating 94 | 95 | nativeMain.dependsOn(commonMain) 96 | nativeTest.dependsOn(commonTest) 97 | nativeTest.dependsOn(nativeMain) 98 | 99 | val platformMain = platforms.map { sourceSets.getByName("${it.name}Main") } 100 | val platformTest = platforms.map { sourceSets.getByName("${it.name}Test") } 101 | 102 | platformMain.forEach { 103 | it.dependsOn(nativeMain) 104 | } 105 | 106 | platformTest.forEach { 107 | it.dependsOn(nativeTest) 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /design/BUFFER.md: -------------------------------------------------------------------------------- 1 | ## Buffer 2 | 3 | The goal of IO library is to provide a common interface for all the different types of inputs and outputs, considering 4 | usability and performance. 5 | 6 | The main purpose of IO is read and write arrays of bytes. There is a `ByteArray` - common Kotlin array of bytes 7 | abstraction, but it usually is not the efficient way to represent array of bytes on the platform(`ByteBuffer` on JVM, 8 | `NSData` on iOS, `CPointer` on Native, `ArrayBuffer` on Js and so on). 9 | 10 | So firstly we need a primitive type to abstract array of bytes. 11 | 12 | The `Buffer` is an abstraction to hold some platform primitive byte storage and give simple access to it. 13 | 14 | `Buffer` can hold a `ByteArray`: 15 | 16 | ```kotlin 17 | val message = Buffer("Hello, World!".encodeToByteArray()) 18 | ``` 19 | 20 | You can also allocate buffer with `ByteArray` directly: 21 | 22 | ```kotlin 23 | val message = ByteArrayBuffer(size = 1024) 24 | ``` 25 | 26 | And has most of the `ByteArray` methods: 27 | 28 | ```kotlin 29 | println("My message size is: ${message.size}") 30 | println("It starts with ${buffer[0]}") 31 | ``` 32 | 33 | `Buffer` is also mutable: 34 | 35 | ```kotlin 36 | fun Buffer.fill(value: Byte) { 37 | for (position in buffer.indices) { 38 | buffer[position] = value 39 | } 40 | } 41 | 42 | message.fill(0.toByte()) 43 | ``` 44 | 45 | ## Where My Data is Located? 46 | 47 | Imagine that you want to read some data from stdin. You don't know how much data to expect, so you will likely allocate 48 | some buffer with big enough size in advance: 49 | 50 | ```kotlin 51 | /** Reads StdIn to a [buffer] and returns read count */ 52 | fun readFromStdInTo(buffer: Buffer): Int = TODO() 53 | 54 | val buffer = ByteArrayBuffer(size = 1024) 55 | val readCount = readFromStdInTo(buffer) 56 | ``` 57 | 58 | Now you have a problem: you have to pass some position and `readCount` across all usages of this `buffer`. 59 | Moreover, if you want to use this buffer again without consuming all data, you will need to make all API accepting 60 | indexes: 61 | 62 | ```kotlin 63 | /** Reads StdIn to a [buffer] and returns read count */ 64 | fun readFromStdInTo(buffer: Buffer, offset: Int): Int = TODO() 65 | 66 | val MESSAGE_HEADER_SIZE = 10 67 | val buffer = ByteArrayBuffer(size = 1024) 68 | 69 | var writeIndex = 0 70 | while (writeIndex < MESSAGE_HEADER_SIZE) { 71 | bytesAvailable += readFromStdInTo(buffer, writeIndex) 72 | } 73 | ``` 74 | 75 | Already smells a bit? 76 | Let's implement method that will read data from one buffer and write it to another: 77 | 78 | ```kotlin 79 | fun copyAndLog( 80 | from: Buffer, 81 | fromOffset: Int, 82 | readLength: Int, 83 | to: Buffer, 84 | toWriteOffset: Int 85 | ): Int { 86 | for (index in 0 until readLength) { 87 | val fromIndex = fromOffset + index 88 | val toIndex = toWriteOffset + index 89 | 90 | val byte = from[fromIndex] 91 | println("Copy byte: $byte") 92 | 93 | to[toIndex] = byte 94 | } 95 | } 96 | ``` 97 | 98 | Or you can write it like this: 99 | 100 | ```kotlin 101 | fun copyAndLog( 102 | from: Buffer, 103 | fromStartIndex: Int, 104 | fromEndIndex: Int, 105 | to: Buffer, 106 | toStartIndex: Int 107 | ): Int { 108 | for (index in 0 until (fromEndIndex - fromStartIndex)) { 109 | val fromIndex = fromStartIndex + index 110 | val toIndex = toStartIndex + index 111 | 112 | val byte = from[fromIndex] 113 | println("Copy byte: $byte") 114 | to[toIndex] = byte 115 | } 116 | } 117 | ``` 118 | 119 | So we have lots of opinionated ways of making a single stuff with indexes, offsets. It looks nasty in combination. 120 | 121 | Let's make it a bit simpler: 122 | 123 | ## Buffer indexes 124 | 125 | The `Buffer` keep track of positions where data is in the `readPosition`, and where you can write it in 126 | the `writePosition`. They are public and mutable: 127 | 128 | ```kotlin 129 | fun copyAndLog(from: Buffer, to: Buffer) { 130 | for (index in from.readPosition until from.writePosition) { 131 | val byte = from[index] 132 | println("Copy byte: $byte") 133 | to[index] = byte 134 | } 135 | 136 | val bytesCount = from.writePosition - from.readPosition 137 | to.writePosition += bytesCount 138 | from.readPosition += bytesCount 139 | } 140 | ``` 141 | 142 | It looks similar to `ByteBuffer.position/limit`, but doesn't require developer to track the Buffer state. 143 | 144 | ## How to Connect the Buffer With All My Data Classes? 145 | 146 | Imagine you have a class: 147 | 148 | ```kotlin 149 | data class User( 150 | val id: Long, 151 | val name: String, 152 | val age: Int, 153 | val email: String 154 | ) 155 | ``` 156 | 157 | To send it over the network you need to convert it to bytes. 158 | Using get and set methods are not convenient: you have to encode each field manually. 159 | 160 | There are some utility methods to help you: 161 | 162 | ```kotlin 163 | fun Buffer.writeUser(user: User) { 164 | with(user) { 165 | writeLong(id) 166 | writeInt(name.length) 167 | writeBytes(name.encodeToByteArray()) 168 | writeInt(age) 169 | writeInt(email.length) 170 | writeBytes(email.encodeToByteArray()) 171 | } 172 | } 173 | ``` 174 | 175 | ```kotlin 176 | fun Buffer.readUser(): User { 177 | val id = readLong() 178 | val nameLength = readInt() 179 | val name = Strign(readBytes(nameLength)) 180 | val age = readInt() 181 | val emailLength = readInt() 182 | val email = String(readBytes(emailLength)) 183 | 184 | return User(id, name, age, email) 185 | } 186 | ``` 187 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=1.0.0-SNAPSHOT 2 | 3 | kotlin.code.style=official 4 | kotlin.js.generate.executable.default=false 5 | kotlin.native.binary.memoryModel=experimental 6 | kotlin.incremental.js=true 7 | kotlin.incremental.multiplatform=true 8 | kotlin.native.ignoreIncorrectDependencies=true 9 | kotlin.native.ignoreDisabledTargets=true 10 | kotlin.mpp.stability.nowarn=true 11 | kotlin.mpp.enableCompatibilityMetadataVariant=true 12 | kotlin.mpp.enableCInteropCommonization=true 13 | kotlin.internal.mpp.hierarchicalStructureByDefault=true 14 | 15 | # versions 16 | coroutines_version=1.6.4 17 | atomicfu_version=0.18.3 18 | kotlin_version=1.7.10 19 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktorio/ktor-io/315c48062a9c050d27a5bc87d2775c875e2c245b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /kotlin-js-store/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@colors/colors@1.5.0": 6 | version "1.5.0" 7 | resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" 8 | integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== 9 | 10 | "@discoveryjs/json-ext@^0.5.0": 11 | version "0.5.7" 12 | resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" 13 | integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== 14 | 15 | "@types/component-emitter@^1.2.10": 16 | version "1.2.11" 17 | resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" 18 | integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== 19 | 20 | "@types/cookie@^0.4.1": 21 | version "0.4.1" 22 | resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" 23 | integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== 24 | 25 | "@types/cors@^2.8.12": 26 | version "2.8.12" 27 | resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" 28 | integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== 29 | 30 | "@types/eslint-scope@^3.7.3": 31 | version "3.7.4" 32 | resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" 33 | integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== 34 | dependencies: 35 | "@types/eslint" "*" 36 | "@types/estree" "*" 37 | 38 | "@types/eslint@*": 39 | version "8.4.1" 40 | resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" 41 | integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== 42 | dependencies: 43 | "@types/estree" "*" 44 | "@types/json-schema" "*" 45 | 46 | "@types/estree@*", "@types/estree@^0.0.51": 47 | version "0.0.51" 48 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" 49 | integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== 50 | 51 | "@types/json-schema@*", "@types/json-schema@^7.0.8": 52 | version "7.0.11" 53 | resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" 54 | integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== 55 | 56 | "@types/node@*", "@types/node@>=10.0.0": 57 | version "17.0.23" 58 | resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da" 59 | integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== 60 | 61 | "@ungap/promise-all-settled@1.1.2": 62 | version "1.1.2" 63 | resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" 64 | integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== 65 | 66 | "@webassemblyjs/ast@1.11.1": 67 | version "1.11.1" 68 | resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" 69 | integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== 70 | dependencies: 71 | "@webassemblyjs/helper-numbers" "1.11.1" 72 | "@webassemblyjs/helper-wasm-bytecode" "1.11.1" 73 | 74 | "@webassemblyjs/floating-point-hex-parser@1.11.1": 75 | version "1.11.1" 76 | resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" 77 | integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== 78 | 79 | "@webassemblyjs/helper-api-error@1.11.1": 80 | version "1.11.1" 81 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" 82 | integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== 83 | 84 | "@webassemblyjs/helper-buffer@1.11.1": 85 | version "1.11.1" 86 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" 87 | integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== 88 | 89 | "@webassemblyjs/helper-numbers@1.11.1": 90 | version "1.11.1" 91 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" 92 | integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== 93 | dependencies: 94 | "@webassemblyjs/floating-point-hex-parser" "1.11.1" 95 | "@webassemblyjs/helper-api-error" "1.11.1" 96 | "@xtuc/long" "4.2.2" 97 | 98 | "@webassemblyjs/helper-wasm-bytecode@1.11.1": 99 | version "1.11.1" 100 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" 101 | integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== 102 | 103 | "@webassemblyjs/helper-wasm-section@1.11.1": 104 | version "1.11.1" 105 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" 106 | integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== 107 | dependencies: 108 | "@webassemblyjs/ast" "1.11.1" 109 | "@webassemblyjs/helper-buffer" "1.11.1" 110 | "@webassemblyjs/helper-wasm-bytecode" "1.11.1" 111 | "@webassemblyjs/wasm-gen" "1.11.1" 112 | 113 | "@webassemblyjs/ieee754@1.11.1": 114 | version "1.11.1" 115 | resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" 116 | integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== 117 | dependencies: 118 | "@xtuc/ieee754" "^1.2.0" 119 | 120 | "@webassemblyjs/leb128@1.11.1": 121 | version "1.11.1" 122 | resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" 123 | integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== 124 | dependencies: 125 | "@xtuc/long" "4.2.2" 126 | 127 | "@webassemblyjs/utf8@1.11.1": 128 | version "1.11.1" 129 | resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" 130 | integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== 131 | 132 | "@webassemblyjs/wasm-edit@1.11.1": 133 | version "1.11.1" 134 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" 135 | integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== 136 | dependencies: 137 | "@webassemblyjs/ast" "1.11.1" 138 | "@webassemblyjs/helper-buffer" "1.11.1" 139 | "@webassemblyjs/helper-wasm-bytecode" "1.11.1" 140 | "@webassemblyjs/helper-wasm-section" "1.11.1" 141 | "@webassemblyjs/wasm-gen" "1.11.1" 142 | "@webassemblyjs/wasm-opt" "1.11.1" 143 | "@webassemblyjs/wasm-parser" "1.11.1" 144 | "@webassemblyjs/wast-printer" "1.11.1" 145 | 146 | "@webassemblyjs/wasm-gen@1.11.1": 147 | version "1.11.1" 148 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" 149 | integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== 150 | dependencies: 151 | "@webassemblyjs/ast" "1.11.1" 152 | "@webassemblyjs/helper-wasm-bytecode" "1.11.1" 153 | "@webassemblyjs/ieee754" "1.11.1" 154 | "@webassemblyjs/leb128" "1.11.1" 155 | "@webassemblyjs/utf8" "1.11.1" 156 | 157 | "@webassemblyjs/wasm-opt@1.11.1": 158 | version "1.11.1" 159 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" 160 | integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== 161 | dependencies: 162 | "@webassemblyjs/ast" "1.11.1" 163 | "@webassemblyjs/helper-buffer" "1.11.1" 164 | "@webassemblyjs/wasm-gen" "1.11.1" 165 | "@webassemblyjs/wasm-parser" "1.11.1" 166 | 167 | "@webassemblyjs/wasm-parser@1.11.1": 168 | version "1.11.1" 169 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" 170 | integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== 171 | dependencies: 172 | "@webassemblyjs/ast" "1.11.1" 173 | "@webassemblyjs/helper-api-error" "1.11.1" 174 | "@webassemblyjs/helper-wasm-bytecode" "1.11.1" 175 | "@webassemblyjs/ieee754" "1.11.1" 176 | "@webassemblyjs/leb128" "1.11.1" 177 | "@webassemblyjs/utf8" "1.11.1" 178 | 179 | "@webassemblyjs/wast-printer@1.11.1": 180 | version "1.11.1" 181 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" 182 | integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== 183 | dependencies: 184 | "@webassemblyjs/ast" "1.11.1" 185 | "@xtuc/long" "4.2.2" 186 | 187 | "@webpack-cli/configtest@^1.2.0": 188 | version "1.2.0" 189 | resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" 190 | integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== 191 | 192 | "@webpack-cli/info@^1.5.0": 193 | version "1.5.0" 194 | resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" 195 | integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== 196 | dependencies: 197 | envinfo "^7.7.3" 198 | 199 | "@webpack-cli/serve@^1.7.0": 200 | version "1.7.0" 201 | resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" 202 | integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== 203 | 204 | "@xtuc/ieee754@^1.2.0": 205 | version "1.2.0" 206 | resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" 207 | integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== 208 | 209 | "@xtuc/long@4.2.2": 210 | version "4.2.2" 211 | resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" 212 | integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== 213 | 214 | abab@^2.0.6: 215 | version "2.0.6" 216 | resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" 217 | integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== 218 | 219 | accepts@~1.3.4: 220 | version "1.3.8" 221 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 222 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 223 | dependencies: 224 | mime-types "~2.1.34" 225 | negotiator "0.6.3" 226 | 227 | acorn-import-assertions@^1.7.6: 228 | version "1.8.0" 229 | resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" 230 | integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== 231 | 232 | acorn@^8.4.1, acorn@^8.5.0: 233 | version "8.7.0" 234 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" 235 | integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== 236 | 237 | ajv-keywords@^3.5.2: 238 | version "3.5.2" 239 | resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" 240 | integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== 241 | 242 | ajv@^6.12.5: 243 | version "6.12.6" 244 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 245 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 246 | dependencies: 247 | fast-deep-equal "^3.1.1" 248 | fast-json-stable-stringify "^2.0.0" 249 | json-schema-traverse "^0.4.1" 250 | uri-js "^4.2.2" 251 | 252 | ansi-colors@4.1.1: 253 | version "4.1.1" 254 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 255 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 256 | 257 | ansi-regex@^5.0.1: 258 | version "5.0.1" 259 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 260 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 261 | 262 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 263 | version "4.3.0" 264 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 265 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 266 | dependencies: 267 | color-convert "^2.0.1" 268 | 269 | anymatch@~3.1.2: 270 | version "3.1.2" 271 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" 272 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 273 | dependencies: 274 | normalize-path "^3.0.0" 275 | picomatch "^2.0.4" 276 | 277 | argparse@^2.0.1: 278 | version "2.0.1" 279 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 280 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 281 | 282 | balanced-match@^1.0.0: 283 | version "1.0.2" 284 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 285 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 286 | 287 | base64id@2.0.0, base64id@~2.0.0: 288 | version "2.0.0" 289 | resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" 290 | integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== 291 | 292 | binary-extensions@^2.0.0: 293 | version "2.2.0" 294 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 295 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 296 | 297 | body-parser@^1.19.0: 298 | version "1.20.0" 299 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" 300 | integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== 301 | dependencies: 302 | bytes "3.1.2" 303 | content-type "~1.0.4" 304 | debug "2.6.9" 305 | depd "2.0.0" 306 | destroy "1.2.0" 307 | http-errors "2.0.0" 308 | iconv-lite "0.4.24" 309 | on-finished "2.4.1" 310 | qs "6.10.3" 311 | raw-body "2.5.1" 312 | type-is "~1.6.18" 313 | unpipe "1.0.0" 314 | 315 | brace-expansion@^1.1.7: 316 | version "1.1.11" 317 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 318 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 319 | dependencies: 320 | balanced-match "^1.0.0" 321 | concat-map "0.0.1" 322 | 323 | brace-expansion@^2.0.1: 324 | version "2.0.1" 325 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 326 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 327 | dependencies: 328 | balanced-match "^1.0.0" 329 | 330 | braces@^3.0.2, braces@~3.0.2: 331 | version "3.0.2" 332 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 333 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 334 | dependencies: 335 | fill-range "^7.0.1" 336 | 337 | browser-stdout@1.3.1: 338 | version "1.3.1" 339 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 340 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 341 | 342 | browserslist@^4.14.5: 343 | version "4.20.2" 344 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88" 345 | integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA== 346 | dependencies: 347 | caniuse-lite "^1.0.30001317" 348 | electron-to-chromium "^1.4.84" 349 | escalade "^3.1.1" 350 | node-releases "^2.0.2" 351 | picocolors "^1.0.0" 352 | 353 | buffer-from@^1.0.0: 354 | version "1.1.2" 355 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 356 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 357 | 358 | bytes@3.1.2: 359 | version "3.1.2" 360 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 361 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 362 | 363 | call-bind@^1.0.0: 364 | version "1.0.2" 365 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 366 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 367 | dependencies: 368 | function-bind "^1.1.1" 369 | get-intrinsic "^1.0.2" 370 | 371 | camelcase@^6.0.0: 372 | version "6.3.0" 373 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 374 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 375 | 376 | caniuse-lite@^1.0.30001317: 377 | version "1.0.30001325" 378 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz#2b4ad19b77aa36f61f2eaf72e636d7481d55e606" 379 | integrity sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ== 380 | 381 | chalk@^4.1.0: 382 | version "4.1.2" 383 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 384 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 385 | dependencies: 386 | ansi-styles "^4.1.0" 387 | supports-color "^7.1.0" 388 | 389 | chokidar@3.5.3, chokidar@^3.5.1: 390 | version "3.5.3" 391 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 392 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 393 | dependencies: 394 | anymatch "~3.1.2" 395 | braces "~3.0.2" 396 | glob-parent "~5.1.2" 397 | is-binary-path "~2.1.0" 398 | is-glob "~4.0.1" 399 | normalize-path "~3.0.0" 400 | readdirp "~3.6.0" 401 | optionalDependencies: 402 | fsevents "~2.3.2" 403 | 404 | chrome-trace-event@^1.0.2: 405 | version "1.0.3" 406 | resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" 407 | integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== 408 | 409 | cliui@^7.0.2: 410 | version "7.0.4" 411 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 412 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 413 | dependencies: 414 | string-width "^4.2.0" 415 | strip-ansi "^6.0.0" 416 | wrap-ansi "^7.0.0" 417 | 418 | clone-deep@^4.0.1: 419 | version "4.0.1" 420 | resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" 421 | integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== 422 | dependencies: 423 | is-plain-object "^2.0.4" 424 | kind-of "^6.0.2" 425 | shallow-clone "^3.0.0" 426 | 427 | color-convert@^2.0.1: 428 | version "2.0.1" 429 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 430 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 431 | dependencies: 432 | color-name "~1.1.4" 433 | 434 | color-name@~1.1.4: 435 | version "1.1.4" 436 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 437 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 438 | 439 | colorette@^2.0.14: 440 | version "2.0.16" 441 | resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" 442 | integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== 443 | 444 | commander@^2.20.0: 445 | version "2.20.3" 446 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 447 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 448 | 449 | commander@^7.0.0: 450 | version "7.2.0" 451 | resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" 452 | integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== 453 | 454 | component-emitter@~1.3.0: 455 | version "1.3.0" 456 | resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" 457 | integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== 458 | 459 | concat-map@0.0.1: 460 | version "0.0.1" 461 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 462 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 463 | 464 | connect@^3.7.0: 465 | version "3.7.0" 466 | resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" 467 | integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== 468 | dependencies: 469 | debug "2.6.9" 470 | finalhandler "1.1.2" 471 | parseurl "~1.3.3" 472 | utils-merge "1.0.1" 473 | 474 | content-type@~1.0.4: 475 | version "1.0.4" 476 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 477 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 478 | 479 | cookie@~0.4.1: 480 | version "0.4.2" 481 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" 482 | integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== 483 | 484 | cors@~2.8.5: 485 | version "2.8.5" 486 | resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" 487 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== 488 | dependencies: 489 | object-assign "^4" 490 | vary "^1" 491 | 492 | cross-spawn@^7.0.3: 493 | version "7.0.3" 494 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 495 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 496 | dependencies: 497 | path-key "^3.1.0" 498 | shebang-command "^2.0.0" 499 | which "^2.0.1" 500 | 501 | custom-event@~1.0.0: 502 | version "1.0.1" 503 | resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" 504 | integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= 505 | 506 | date-format@^4.0.10: 507 | version "4.0.11" 508 | resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.11.tgz#ae0d1e069d7f0687938fd06f98c12f3a6276e526" 509 | integrity sha512-VS20KRyorrbMCQmpdl2hg5KaOUsda1RbnsJg461FfrcyCUg+pkd0b40BSW4niQyTheww4DBXQnS7HwSrKkipLw== 510 | 511 | debug@2.6.9: 512 | version "2.6.9" 513 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 514 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 515 | dependencies: 516 | ms "2.0.0" 517 | 518 | debug@4.3.4, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: 519 | version "4.3.4" 520 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 521 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 522 | dependencies: 523 | ms "2.1.2" 524 | 525 | decamelize@^4.0.0: 526 | version "4.0.0" 527 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 528 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 529 | 530 | depd@2.0.0: 531 | version "2.0.0" 532 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 533 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 534 | 535 | destroy@1.2.0: 536 | version "1.2.0" 537 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 538 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 539 | 540 | di@^0.0.1: 541 | version "0.0.1" 542 | resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" 543 | integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= 544 | 545 | diff@5.0.0: 546 | version "5.0.0" 547 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 548 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 549 | 550 | dom-serialize@^2.2.1: 551 | version "2.2.1" 552 | resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" 553 | integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs= 554 | dependencies: 555 | custom-event "~1.0.0" 556 | ent "~2.2.0" 557 | extend "^3.0.0" 558 | void-elements "^2.0.0" 559 | 560 | ee-first@1.1.1: 561 | version "1.1.1" 562 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 563 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 564 | 565 | electron-to-chromium@^1.4.84: 566 | version "1.4.105" 567 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.105.tgz#30de5e4ba020140b698539b2d366cd9c3a337ec7" 568 | integrity sha512-6w2bmoQBSUgCQjbSjiVv9IS1lXwW2aQABlUJ1vlE8Vci/sVXxUNQrHLQa5N1ioc82Py+a36DlUA5KvrAlHMMeA== 569 | 570 | emoji-regex@^8.0.0: 571 | version "8.0.0" 572 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 573 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 574 | 575 | encodeurl@~1.0.2: 576 | version "1.0.2" 577 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 578 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 579 | 580 | engine.io-parser@~5.0.3: 581 | version "5.0.4" 582 | resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0" 583 | integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg== 584 | 585 | engine.io@~6.2.0: 586 | version "6.2.0" 587 | resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0" 588 | integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg== 589 | dependencies: 590 | "@types/cookie" "^0.4.1" 591 | "@types/cors" "^2.8.12" 592 | "@types/node" ">=10.0.0" 593 | accepts "~1.3.4" 594 | base64id "2.0.0" 595 | cookie "~0.4.1" 596 | cors "~2.8.5" 597 | debug "~4.3.1" 598 | engine.io-parser "~5.0.3" 599 | ws "~8.2.3" 600 | 601 | enhanced-resolve@^5.9.3: 602 | version "5.10.0" 603 | resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" 604 | integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== 605 | dependencies: 606 | graceful-fs "^4.2.4" 607 | tapable "^2.2.0" 608 | 609 | ent@~2.2.0: 610 | version "2.2.0" 611 | resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" 612 | integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= 613 | 614 | envinfo@^7.7.3: 615 | version "7.8.1" 616 | resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" 617 | integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== 618 | 619 | es-module-lexer@^0.9.0: 620 | version "0.9.3" 621 | resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" 622 | integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== 623 | 624 | escalade@^3.1.1: 625 | version "3.1.1" 626 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 627 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 628 | 629 | escape-html@~1.0.3: 630 | version "1.0.3" 631 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 632 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 633 | 634 | escape-string-regexp@4.0.0: 635 | version "4.0.0" 636 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 637 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 638 | 639 | eslint-scope@5.1.1: 640 | version "5.1.1" 641 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 642 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 643 | dependencies: 644 | esrecurse "^4.3.0" 645 | estraverse "^4.1.1" 646 | 647 | esrecurse@^4.3.0: 648 | version "4.3.0" 649 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 650 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 651 | dependencies: 652 | estraverse "^5.2.0" 653 | 654 | estraverse@^4.1.1: 655 | version "4.3.0" 656 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 657 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 658 | 659 | estraverse@^5.2.0: 660 | version "5.3.0" 661 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 662 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 663 | 664 | eventemitter3@^4.0.0: 665 | version "4.0.7" 666 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" 667 | integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== 668 | 669 | events@^3.2.0: 670 | version "3.3.0" 671 | resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" 672 | integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== 673 | 674 | extend@^3.0.0: 675 | version "3.0.2" 676 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 677 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 678 | 679 | fast-deep-equal@^3.1.1: 680 | version "3.1.3" 681 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 682 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 683 | 684 | fast-json-stable-stringify@^2.0.0: 685 | version "2.1.0" 686 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 687 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 688 | 689 | fastest-levenshtein@^1.0.12: 690 | version "1.0.12" 691 | resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" 692 | integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== 693 | 694 | fill-range@^7.0.1: 695 | version "7.0.1" 696 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 697 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 698 | dependencies: 699 | to-regex-range "^5.0.1" 700 | 701 | finalhandler@1.1.2: 702 | version "1.1.2" 703 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" 704 | integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== 705 | dependencies: 706 | debug "2.6.9" 707 | encodeurl "~1.0.2" 708 | escape-html "~1.0.3" 709 | on-finished "~2.3.0" 710 | parseurl "~1.3.3" 711 | statuses "~1.5.0" 712 | unpipe "~1.0.0" 713 | 714 | find-up@5.0.0: 715 | version "5.0.0" 716 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 717 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 718 | dependencies: 719 | locate-path "^6.0.0" 720 | path-exists "^4.0.0" 721 | 722 | find-up@^4.0.0: 723 | version "4.1.0" 724 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 725 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 726 | dependencies: 727 | locate-path "^5.0.0" 728 | path-exists "^4.0.0" 729 | 730 | flat@^5.0.2: 731 | version "5.0.2" 732 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 733 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 734 | 735 | flatted@^3.2.5: 736 | version "3.2.5" 737 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" 738 | integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== 739 | 740 | follow-redirects@^1.0.0: 741 | version "1.14.9" 742 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" 743 | integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== 744 | 745 | format-util@1.0.5: 746 | version "1.0.5" 747 | resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" 748 | integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== 749 | 750 | fs-extra@^10.1.0: 751 | version "10.1.0" 752 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" 753 | integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== 754 | dependencies: 755 | graceful-fs "^4.2.0" 756 | jsonfile "^6.0.1" 757 | universalify "^2.0.0" 758 | 759 | fs.realpath@^1.0.0: 760 | version "1.0.0" 761 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 762 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 763 | 764 | fsevents@~2.3.2: 765 | version "2.3.2" 766 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 767 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 768 | 769 | function-bind@^1.1.1: 770 | version "1.1.1" 771 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 772 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 773 | 774 | get-caller-file@^2.0.5: 775 | version "2.0.5" 776 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 777 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 778 | 779 | get-intrinsic@^1.0.2: 780 | version "1.1.1" 781 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" 782 | integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== 783 | dependencies: 784 | function-bind "^1.1.1" 785 | has "^1.0.3" 786 | has-symbols "^1.0.1" 787 | 788 | glob-parent@~5.1.2: 789 | version "5.1.2" 790 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 791 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 792 | dependencies: 793 | is-glob "^4.0.1" 794 | 795 | glob-to-regexp@^0.4.1: 796 | version "0.4.1" 797 | resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" 798 | integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== 799 | 800 | glob@7.2.0, glob@^7.1.3, glob@^7.1.7: 801 | version "7.2.0" 802 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 803 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 804 | dependencies: 805 | fs.realpath "^1.0.0" 806 | inflight "^1.0.4" 807 | inherits "2" 808 | minimatch "^3.0.4" 809 | once "^1.3.0" 810 | path-is-absolute "^1.0.0" 811 | 812 | graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: 813 | version "4.2.10" 814 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" 815 | integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== 816 | 817 | has-flag@^4.0.0: 818 | version "4.0.0" 819 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 820 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 821 | 822 | has-symbols@^1.0.1: 823 | version "1.0.3" 824 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 825 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 826 | 827 | has@^1.0.3: 828 | version "1.0.3" 829 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 830 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 831 | dependencies: 832 | function-bind "^1.1.1" 833 | 834 | he@1.2.0: 835 | version "1.2.0" 836 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 837 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 838 | 839 | http-errors@2.0.0: 840 | version "2.0.0" 841 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 842 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 843 | dependencies: 844 | depd "2.0.0" 845 | inherits "2.0.4" 846 | setprototypeof "1.2.0" 847 | statuses "2.0.1" 848 | toidentifier "1.0.1" 849 | 850 | http-proxy@^1.18.1: 851 | version "1.18.1" 852 | resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" 853 | integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== 854 | dependencies: 855 | eventemitter3 "^4.0.0" 856 | follow-redirects "^1.0.0" 857 | requires-port "^1.0.0" 858 | 859 | iconv-lite@0.4.24: 860 | version "0.4.24" 861 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 862 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 863 | dependencies: 864 | safer-buffer ">= 2.1.2 < 3" 865 | 866 | iconv-lite@^0.6.3: 867 | version "0.6.3" 868 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" 869 | integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== 870 | dependencies: 871 | safer-buffer ">= 2.1.2 < 3.0.0" 872 | 873 | import-local@^3.0.2: 874 | version "3.1.0" 875 | resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" 876 | integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== 877 | dependencies: 878 | pkg-dir "^4.2.0" 879 | resolve-cwd "^3.0.0" 880 | 881 | inflight@^1.0.4: 882 | version "1.0.6" 883 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 884 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 885 | dependencies: 886 | once "^1.3.0" 887 | wrappy "1" 888 | 889 | inherits@2, inherits@2.0.4: 890 | version "2.0.4" 891 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 892 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 893 | 894 | interpret@^2.2.0: 895 | version "2.2.0" 896 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" 897 | integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== 898 | 899 | is-binary-path@~2.1.0: 900 | version "2.1.0" 901 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 902 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 903 | dependencies: 904 | binary-extensions "^2.0.0" 905 | 906 | is-core-module@^2.8.1: 907 | version "2.8.1" 908 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" 909 | integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== 910 | dependencies: 911 | has "^1.0.3" 912 | 913 | is-extglob@^2.1.1: 914 | version "2.1.1" 915 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 916 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 917 | 918 | is-fullwidth-code-point@^3.0.0: 919 | version "3.0.0" 920 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 921 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 922 | 923 | is-glob@^4.0.1, is-glob@~4.0.1: 924 | version "4.0.3" 925 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 926 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 927 | dependencies: 928 | is-extglob "^2.1.1" 929 | 930 | is-number@^7.0.0: 931 | version "7.0.0" 932 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 933 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 934 | 935 | is-plain-obj@^2.1.0: 936 | version "2.1.0" 937 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 938 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 939 | 940 | is-plain-object@^2.0.4: 941 | version "2.0.4" 942 | resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" 943 | integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== 944 | dependencies: 945 | isobject "^3.0.1" 946 | 947 | is-unicode-supported@^0.1.0: 948 | version "0.1.0" 949 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 950 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 951 | 952 | isbinaryfile@^4.0.8: 953 | version "4.0.10" 954 | resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" 955 | integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== 956 | 957 | isexe@^2.0.0: 958 | version "2.0.0" 959 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 960 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 961 | 962 | isobject@^3.0.1: 963 | version "3.0.1" 964 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" 965 | integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= 966 | 967 | jest-worker@^27.4.5: 968 | version "27.5.1" 969 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" 970 | integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== 971 | dependencies: 972 | "@types/node" "*" 973 | merge-stream "^2.0.0" 974 | supports-color "^8.0.0" 975 | 976 | js-yaml@4.1.0: 977 | version "4.1.0" 978 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 979 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 980 | dependencies: 981 | argparse "^2.0.1" 982 | 983 | json-parse-even-better-errors@^2.3.1: 984 | version "2.3.1" 985 | resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" 986 | integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 987 | 988 | json-schema-traverse@^0.4.1: 989 | version "0.4.1" 990 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 991 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 992 | 993 | jsonfile@^6.0.1: 994 | version "6.1.0" 995 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" 996 | integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== 997 | dependencies: 998 | universalify "^2.0.0" 999 | optionalDependencies: 1000 | graceful-fs "^4.1.6" 1001 | 1002 | karma-chrome-launcher@3.1.1: 1003 | version "3.1.1" 1004 | resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz#baca9cc071b1562a1db241827257bfe5cab597ea" 1005 | integrity sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ== 1006 | dependencies: 1007 | which "^1.2.1" 1008 | 1009 | karma-mocha@2.0.1: 1010 | version "2.0.1" 1011 | resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" 1012 | integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== 1013 | dependencies: 1014 | minimist "^1.2.3" 1015 | 1016 | karma-sourcemap-loader@0.3.8: 1017 | version "0.3.8" 1018 | resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.8.tgz#d4bae72fb7a8397328a62b75013d2df937bdcf9c" 1019 | integrity sha512-zorxyAakYZuBcHRJE+vbrK2o2JXLFWK8VVjiT/6P+ltLBUGUvqTEkUiQ119MGdOrK7mrmxXHZF1/pfT6GgIZ6g== 1020 | dependencies: 1021 | graceful-fs "^4.1.2" 1022 | 1023 | karma-webpack@5.0.0: 1024 | version "5.0.0" 1025 | resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.0.tgz#2a2c7b80163fe7ffd1010f83f5507f95ef39f840" 1026 | integrity sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA== 1027 | dependencies: 1028 | glob "^7.1.3" 1029 | minimatch "^3.0.4" 1030 | webpack-merge "^4.1.5" 1031 | 1032 | karma@6.4.0: 1033 | version "6.4.0" 1034 | resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.0.tgz#82652dfecdd853ec227b74ed718a997028a99508" 1035 | integrity sha512-s8m7z0IF5g/bS5ONT7wsOavhW4i4aFkzD4u4wgzAQWT4HGUeWI3i21cK2Yz6jndMAeHETp5XuNsRoyGJZXVd4w== 1036 | dependencies: 1037 | "@colors/colors" "1.5.0" 1038 | body-parser "^1.19.0" 1039 | braces "^3.0.2" 1040 | chokidar "^3.5.1" 1041 | connect "^3.7.0" 1042 | di "^0.0.1" 1043 | dom-serialize "^2.2.1" 1044 | glob "^7.1.7" 1045 | graceful-fs "^4.2.6" 1046 | http-proxy "^1.18.1" 1047 | isbinaryfile "^4.0.8" 1048 | lodash "^4.17.21" 1049 | log4js "^6.4.1" 1050 | mime "^2.5.2" 1051 | minimatch "^3.0.4" 1052 | mkdirp "^0.5.5" 1053 | qjobs "^1.2.0" 1054 | range-parser "^1.2.1" 1055 | rimraf "^3.0.2" 1056 | socket.io "^4.4.1" 1057 | source-map "^0.6.1" 1058 | tmp "^0.2.1" 1059 | ua-parser-js "^0.7.30" 1060 | yargs "^16.1.1" 1061 | 1062 | kind-of@^6.0.2: 1063 | version "6.0.3" 1064 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 1065 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 1066 | 1067 | loader-runner@^4.2.0: 1068 | version "4.2.0" 1069 | resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" 1070 | integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== 1071 | 1072 | locate-path@^5.0.0: 1073 | version "5.0.0" 1074 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 1075 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 1076 | dependencies: 1077 | p-locate "^4.1.0" 1078 | 1079 | locate-path@^6.0.0: 1080 | version "6.0.0" 1081 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 1082 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 1083 | dependencies: 1084 | p-locate "^5.0.0" 1085 | 1086 | lodash@^4.17.15, lodash@^4.17.21: 1087 | version "4.17.21" 1088 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 1089 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 1090 | 1091 | log-symbols@4.1.0: 1092 | version "4.1.0" 1093 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 1094 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 1095 | dependencies: 1096 | chalk "^4.1.0" 1097 | is-unicode-supported "^0.1.0" 1098 | 1099 | log4js@^6.4.1: 1100 | version "6.5.2" 1101 | resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.5.2.tgz#9ae371e5b3cb3a3a209c24686e5547f8670834e5" 1102 | integrity sha512-DXtpNtt+KDOMT7RHUDIur/WsSA3rntlUh9Zg4XCdV42wUuMmbFkl38+LZ92Z5QvQA7mD5kAVkLiBSEH/tvUB8A== 1103 | dependencies: 1104 | date-format "^4.0.10" 1105 | debug "^4.3.4" 1106 | flatted "^3.2.5" 1107 | rfdc "^1.3.0" 1108 | streamroller "^3.1.1" 1109 | 1110 | media-typer@0.3.0: 1111 | version "0.3.0" 1112 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 1113 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= 1114 | 1115 | merge-stream@^2.0.0: 1116 | version "2.0.0" 1117 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 1118 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 1119 | 1120 | mime-db@1.52.0: 1121 | version "1.52.0" 1122 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 1123 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 1124 | 1125 | mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: 1126 | version "2.1.35" 1127 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 1128 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 1129 | dependencies: 1130 | mime-db "1.52.0" 1131 | 1132 | mime@^2.5.2: 1133 | version "2.6.0" 1134 | resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" 1135 | integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== 1136 | 1137 | minimatch@5.0.1: 1138 | version "5.0.1" 1139 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" 1140 | integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== 1141 | dependencies: 1142 | brace-expansion "^2.0.1" 1143 | 1144 | minimatch@^3.0.4: 1145 | version "3.1.2" 1146 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 1147 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1148 | dependencies: 1149 | brace-expansion "^1.1.7" 1150 | 1151 | minimist@^1.2.3, minimist@^1.2.6: 1152 | version "1.2.6" 1153 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" 1154 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== 1155 | 1156 | mkdirp@^0.5.5: 1157 | version "0.5.6" 1158 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 1159 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 1160 | dependencies: 1161 | minimist "^1.2.6" 1162 | 1163 | mocha@10.0.0: 1164 | version "10.0.0" 1165 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9" 1166 | integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA== 1167 | dependencies: 1168 | "@ungap/promise-all-settled" "1.1.2" 1169 | ansi-colors "4.1.1" 1170 | browser-stdout "1.3.1" 1171 | chokidar "3.5.3" 1172 | debug "4.3.4" 1173 | diff "5.0.0" 1174 | escape-string-regexp "4.0.0" 1175 | find-up "5.0.0" 1176 | glob "7.2.0" 1177 | he "1.2.0" 1178 | js-yaml "4.1.0" 1179 | log-symbols "4.1.0" 1180 | minimatch "5.0.1" 1181 | ms "2.1.3" 1182 | nanoid "3.3.3" 1183 | serialize-javascript "6.0.0" 1184 | strip-json-comments "3.1.1" 1185 | supports-color "8.1.1" 1186 | workerpool "6.2.1" 1187 | yargs "16.2.0" 1188 | yargs-parser "20.2.4" 1189 | yargs-unparser "2.0.0" 1190 | 1191 | ms@2.0.0: 1192 | version "2.0.0" 1193 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 1194 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 1195 | 1196 | ms@2.1.2: 1197 | version "2.1.2" 1198 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1199 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1200 | 1201 | ms@2.1.3: 1202 | version "2.1.3" 1203 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1204 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1205 | 1206 | nanoid@3.3.3: 1207 | version "3.3.3" 1208 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" 1209 | integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== 1210 | 1211 | negotiator@0.6.3: 1212 | version "0.6.3" 1213 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 1214 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 1215 | 1216 | neo-async@^2.6.2: 1217 | version "2.6.2" 1218 | resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" 1219 | integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== 1220 | 1221 | node-releases@^2.0.2: 1222 | version "2.0.2" 1223 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" 1224 | integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== 1225 | 1226 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1227 | version "3.0.0" 1228 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1229 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1230 | 1231 | object-assign@^4: 1232 | version "4.1.1" 1233 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1234 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 1235 | 1236 | object-inspect@^1.9.0: 1237 | version "1.12.0" 1238 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" 1239 | integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== 1240 | 1241 | on-finished@2.4.1: 1242 | version "2.4.1" 1243 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 1244 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 1245 | dependencies: 1246 | ee-first "1.1.1" 1247 | 1248 | on-finished@~2.3.0: 1249 | version "2.3.0" 1250 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 1251 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 1252 | dependencies: 1253 | ee-first "1.1.1" 1254 | 1255 | once@^1.3.0: 1256 | version "1.4.0" 1257 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1258 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1259 | dependencies: 1260 | wrappy "1" 1261 | 1262 | p-limit@^2.2.0: 1263 | version "2.3.0" 1264 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 1265 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 1266 | dependencies: 1267 | p-try "^2.0.0" 1268 | 1269 | p-limit@^3.0.2: 1270 | version "3.1.0" 1271 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1272 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1273 | dependencies: 1274 | yocto-queue "^0.1.0" 1275 | 1276 | p-locate@^4.1.0: 1277 | version "4.1.0" 1278 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 1279 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 1280 | dependencies: 1281 | p-limit "^2.2.0" 1282 | 1283 | p-locate@^5.0.0: 1284 | version "5.0.0" 1285 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1286 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1287 | dependencies: 1288 | p-limit "^3.0.2" 1289 | 1290 | p-try@^2.0.0: 1291 | version "2.2.0" 1292 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 1293 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 1294 | 1295 | parseurl@~1.3.3: 1296 | version "1.3.3" 1297 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 1298 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 1299 | 1300 | path-exists@^4.0.0: 1301 | version "4.0.0" 1302 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1303 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1304 | 1305 | path-is-absolute@^1.0.0: 1306 | version "1.0.1" 1307 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1308 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1309 | 1310 | path-key@^3.1.0: 1311 | version "3.1.1" 1312 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1313 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1314 | 1315 | path-parse@^1.0.7: 1316 | version "1.0.7" 1317 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 1318 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1319 | 1320 | picocolors@^1.0.0: 1321 | version "1.0.0" 1322 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 1323 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 1324 | 1325 | picomatch@^2.0.4, picomatch@^2.2.1: 1326 | version "2.3.1" 1327 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1328 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1329 | 1330 | pkg-dir@^4.2.0: 1331 | version "4.2.0" 1332 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 1333 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 1334 | dependencies: 1335 | find-up "^4.0.0" 1336 | 1337 | punycode@^2.1.0: 1338 | version "2.1.1" 1339 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 1340 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 1341 | 1342 | qjobs@^1.2.0: 1343 | version "1.2.0" 1344 | resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" 1345 | integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== 1346 | 1347 | qs@6.10.3: 1348 | version "6.10.3" 1349 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" 1350 | integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== 1351 | dependencies: 1352 | side-channel "^1.0.4" 1353 | 1354 | randombytes@^2.1.0: 1355 | version "2.1.0" 1356 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1357 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1358 | dependencies: 1359 | safe-buffer "^5.1.0" 1360 | 1361 | range-parser@^1.2.1: 1362 | version "1.2.1" 1363 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 1364 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 1365 | 1366 | raw-body@2.5.1: 1367 | version "2.5.1" 1368 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 1369 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 1370 | dependencies: 1371 | bytes "3.1.2" 1372 | http-errors "2.0.0" 1373 | iconv-lite "0.4.24" 1374 | unpipe "1.0.0" 1375 | 1376 | readdirp@~3.6.0: 1377 | version "3.6.0" 1378 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 1379 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1380 | dependencies: 1381 | picomatch "^2.2.1" 1382 | 1383 | rechoir@^0.7.0: 1384 | version "0.7.1" 1385 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" 1386 | integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== 1387 | dependencies: 1388 | resolve "^1.9.0" 1389 | 1390 | require-directory@^2.1.1: 1391 | version "2.1.1" 1392 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1393 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= 1394 | 1395 | requires-port@^1.0.0: 1396 | version "1.0.0" 1397 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1398 | integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= 1399 | 1400 | resolve-cwd@^3.0.0: 1401 | version "3.0.0" 1402 | resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" 1403 | integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== 1404 | dependencies: 1405 | resolve-from "^5.0.0" 1406 | 1407 | resolve-from@^5.0.0: 1408 | version "5.0.0" 1409 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 1410 | integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 1411 | 1412 | resolve@^1.9.0: 1413 | version "1.22.0" 1414 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" 1415 | integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== 1416 | dependencies: 1417 | is-core-module "^2.8.1" 1418 | path-parse "^1.0.7" 1419 | supports-preserve-symlinks-flag "^1.0.0" 1420 | 1421 | rfdc@^1.3.0: 1422 | version "1.3.0" 1423 | resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" 1424 | integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== 1425 | 1426 | rimraf@^3.0.0, rimraf@^3.0.2: 1427 | version "3.0.2" 1428 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1429 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1430 | dependencies: 1431 | glob "^7.1.3" 1432 | 1433 | safe-buffer@^5.1.0: 1434 | version "5.2.1" 1435 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1436 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1437 | 1438 | "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": 1439 | version "2.1.2" 1440 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1441 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1442 | 1443 | schema-utils@^3.1.0, schema-utils@^3.1.1: 1444 | version "3.1.1" 1445 | resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" 1446 | integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== 1447 | dependencies: 1448 | "@types/json-schema" "^7.0.8" 1449 | ajv "^6.12.5" 1450 | ajv-keywords "^3.5.2" 1451 | 1452 | serialize-javascript@6.0.0, serialize-javascript@^6.0.0: 1453 | version "6.0.0" 1454 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 1455 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 1456 | dependencies: 1457 | randombytes "^2.1.0" 1458 | 1459 | setprototypeof@1.2.0: 1460 | version "1.2.0" 1461 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1462 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1463 | 1464 | shallow-clone@^3.0.0: 1465 | version "3.0.1" 1466 | resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" 1467 | integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== 1468 | dependencies: 1469 | kind-of "^6.0.2" 1470 | 1471 | shebang-command@^2.0.0: 1472 | version "2.0.0" 1473 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1474 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1475 | dependencies: 1476 | shebang-regex "^3.0.0" 1477 | 1478 | shebang-regex@^3.0.0: 1479 | version "3.0.0" 1480 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1481 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1482 | 1483 | side-channel@^1.0.4: 1484 | version "1.0.4" 1485 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 1486 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 1487 | dependencies: 1488 | call-bind "^1.0.0" 1489 | get-intrinsic "^1.0.2" 1490 | object-inspect "^1.9.0" 1491 | 1492 | socket.io-adapter@~2.4.0: 1493 | version "2.4.0" 1494 | resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6" 1495 | integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg== 1496 | 1497 | socket.io-parser@~4.0.4: 1498 | version "4.0.5" 1499 | resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.5.tgz#cb404382c32324cc962f27f3a44058cf6e0552df" 1500 | integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig== 1501 | dependencies: 1502 | "@types/component-emitter" "^1.2.10" 1503 | component-emitter "~1.3.0" 1504 | debug "~4.3.1" 1505 | 1506 | socket.io@^4.4.1: 1507 | version "4.5.1" 1508 | resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.1.tgz#aa7e73f8a6ce20ee3c54b2446d321bbb6b1a9029" 1509 | integrity sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ== 1510 | dependencies: 1511 | accepts "~1.3.4" 1512 | base64id "~2.0.0" 1513 | debug "~4.3.2" 1514 | engine.io "~6.2.0" 1515 | socket.io-adapter "~2.4.0" 1516 | socket.io-parser "~4.0.4" 1517 | 1518 | source-map-js@^1.0.2: 1519 | version "1.0.2" 1520 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 1521 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 1522 | 1523 | source-map-loader@4.0.0: 1524 | version "4.0.0" 1525 | resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.0.tgz#bdc6b118bc6c87ee4d8d851f2d4efcc5abdb2ef5" 1526 | integrity sha512-i3KVgM3+QPAHNbGavK+VBq03YoJl24m9JWNbLgsjTj8aJzXG9M61bantBTNBt7CNwY2FYf+RJRYJ3pzalKjIrw== 1527 | dependencies: 1528 | abab "^2.0.6" 1529 | iconv-lite "^0.6.3" 1530 | source-map-js "^1.0.2" 1531 | 1532 | source-map-support@0.5.21, source-map-support@~0.5.20: 1533 | version "0.5.21" 1534 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" 1535 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 1536 | dependencies: 1537 | buffer-from "^1.0.0" 1538 | source-map "^0.6.0" 1539 | 1540 | source-map@^0.6.0, source-map@^0.6.1: 1541 | version "0.6.1" 1542 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1543 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1544 | 1545 | source-map@~0.7.2: 1546 | version "0.7.3" 1547 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" 1548 | integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== 1549 | 1550 | statuses@2.0.1: 1551 | version "2.0.1" 1552 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1553 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1554 | 1555 | statuses@~1.5.0: 1556 | version "1.5.0" 1557 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 1558 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= 1559 | 1560 | streamroller@^3.1.1: 1561 | version "3.1.1" 1562 | resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.1.tgz#679aae10a4703acdf2740755307df0a05ad752e6" 1563 | integrity sha512-iPhtd9unZ6zKdWgMeYGfSBuqCngyJy1B/GPi/lTpwGpa3bajuX30GjUVd0/Tn/Xhg0mr4DOSENozz9Y06qyonQ== 1564 | dependencies: 1565 | date-format "^4.0.10" 1566 | debug "^4.3.4" 1567 | fs-extra "^10.1.0" 1568 | 1569 | string-width@^4.1.0, string-width@^4.2.0: 1570 | version "4.2.3" 1571 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1572 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1573 | dependencies: 1574 | emoji-regex "^8.0.0" 1575 | is-fullwidth-code-point "^3.0.0" 1576 | strip-ansi "^6.0.1" 1577 | 1578 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1579 | version "6.0.1" 1580 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1581 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1582 | dependencies: 1583 | ansi-regex "^5.0.1" 1584 | 1585 | strip-json-comments@3.1.1: 1586 | version "3.1.1" 1587 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1588 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1589 | 1590 | supports-color@8.1.1, supports-color@^8.0.0: 1591 | version "8.1.1" 1592 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 1593 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 1594 | dependencies: 1595 | has-flag "^4.0.0" 1596 | 1597 | supports-color@^7.1.0: 1598 | version "7.2.0" 1599 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1600 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1601 | dependencies: 1602 | has-flag "^4.0.0" 1603 | 1604 | supports-preserve-symlinks-flag@^1.0.0: 1605 | version "1.0.0" 1606 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 1607 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 1608 | 1609 | tapable@^2.1.1, tapable@^2.2.0: 1610 | version "2.2.1" 1611 | resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" 1612 | integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== 1613 | 1614 | terser-webpack-plugin@^5.1.3: 1615 | version "5.3.1" 1616 | resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" 1617 | integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== 1618 | dependencies: 1619 | jest-worker "^27.4.5" 1620 | schema-utils "^3.1.1" 1621 | serialize-javascript "^6.0.0" 1622 | source-map "^0.6.1" 1623 | terser "^5.7.2" 1624 | 1625 | terser@^5.7.2: 1626 | version "5.12.1" 1627 | resolved "https://registry.yarnpkg.com/terser/-/terser-5.12.1.tgz#4cf2ebed1f5bceef5c83b9f60104ac4a78b49e9c" 1628 | integrity sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ== 1629 | dependencies: 1630 | acorn "^8.5.0" 1631 | commander "^2.20.0" 1632 | source-map "~0.7.2" 1633 | source-map-support "~0.5.20" 1634 | 1635 | tmp@^0.2.1: 1636 | version "0.2.1" 1637 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" 1638 | integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== 1639 | dependencies: 1640 | rimraf "^3.0.0" 1641 | 1642 | to-regex-range@^5.0.1: 1643 | version "5.0.1" 1644 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1645 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1646 | dependencies: 1647 | is-number "^7.0.0" 1648 | 1649 | toidentifier@1.0.1: 1650 | version "1.0.1" 1651 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1652 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1653 | 1654 | type-is@~1.6.18: 1655 | version "1.6.18" 1656 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 1657 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 1658 | dependencies: 1659 | media-typer "0.3.0" 1660 | mime-types "~2.1.24" 1661 | 1662 | ua-parser-js@^0.7.30: 1663 | version "0.7.31" 1664 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" 1665 | integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== 1666 | 1667 | universalify@^2.0.0: 1668 | version "2.0.0" 1669 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" 1670 | integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== 1671 | 1672 | unpipe@1.0.0, unpipe@~1.0.0: 1673 | version "1.0.0" 1674 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1675 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 1676 | 1677 | uri-js@^4.2.2: 1678 | version "4.4.1" 1679 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1680 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1681 | dependencies: 1682 | punycode "^2.1.0" 1683 | 1684 | utils-merge@1.0.1: 1685 | version "1.0.1" 1686 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 1687 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= 1688 | 1689 | vary@^1: 1690 | version "1.1.2" 1691 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 1692 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 1693 | 1694 | void-elements@^2.0.0: 1695 | version "2.0.1" 1696 | resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" 1697 | integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= 1698 | 1699 | watchpack@^2.3.1: 1700 | version "2.4.0" 1701 | resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" 1702 | integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== 1703 | dependencies: 1704 | glob-to-regexp "^0.4.1" 1705 | graceful-fs "^4.1.2" 1706 | 1707 | webpack-cli@4.10.0: 1708 | version "4.10.0" 1709 | resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" 1710 | integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== 1711 | dependencies: 1712 | "@discoveryjs/json-ext" "^0.5.0" 1713 | "@webpack-cli/configtest" "^1.2.0" 1714 | "@webpack-cli/info" "^1.5.0" 1715 | "@webpack-cli/serve" "^1.7.0" 1716 | colorette "^2.0.14" 1717 | commander "^7.0.0" 1718 | cross-spawn "^7.0.3" 1719 | fastest-levenshtein "^1.0.12" 1720 | import-local "^3.0.2" 1721 | interpret "^2.2.0" 1722 | rechoir "^0.7.0" 1723 | webpack-merge "^5.7.3" 1724 | 1725 | webpack-merge@^4.1.5: 1726 | version "4.2.2" 1727 | resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" 1728 | integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== 1729 | dependencies: 1730 | lodash "^4.17.15" 1731 | 1732 | webpack-merge@^5.7.3: 1733 | version "5.8.0" 1734 | resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" 1735 | integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== 1736 | dependencies: 1737 | clone-deep "^4.0.1" 1738 | wildcard "^2.0.0" 1739 | 1740 | webpack-sources@^3.2.3: 1741 | version "3.2.3" 1742 | resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" 1743 | integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== 1744 | 1745 | webpack@5.73.0: 1746 | version "5.73.0" 1747 | resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.73.0.tgz#bbd17738f8a53ee5760ea2f59dce7f3431d35d38" 1748 | integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA== 1749 | dependencies: 1750 | "@types/eslint-scope" "^3.7.3" 1751 | "@types/estree" "^0.0.51" 1752 | "@webassemblyjs/ast" "1.11.1" 1753 | "@webassemblyjs/wasm-edit" "1.11.1" 1754 | "@webassemblyjs/wasm-parser" "1.11.1" 1755 | acorn "^8.4.1" 1756 | acorn-import-assertions "^1.7.6" 1757 | browserslist "^4.14.5" 1758 | chrome-trace-event "^1.0.2" 1759 | enhanced-resolve "^5.9.3" 1760 | es-module-lexer "^0.9.0" 1761 | eslint-scope "5.1.1" 1762 | events "^3.2.0" 1763 | glob-to-regexp "^0.4.1" 1764 | graceful-fs "^4.2.9" 1765 | json-parse-even-better-errors "^2.3.1" 1766 | loader-runner "^4.2.0" 1767 | mime-types "^2.1.27" 1768 | neo-async "^2.6.2" 1769 | schema-utils "^3.1.0" 1770 | tapable "^2.1.1" 1771 | terser-webpack-plugin "^5.1.3" 1772 | watchpack "^2.3.1" 1773 | webpack-sources "^3.2.3" 1774 | 1775 | which@^1.2.1: 1776 | version "1.3.1" 1777 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1778 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 1779 | dependencies: 1780 | isexe "^2.0.0" 1781 | 1782 | which@^2.0.1: 1783 | version "2.0.2" 1784 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1785 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1786 | dependencies: 1787 | isexe "^2.0.0" 1788 | 1789 | wildcard@^2.0.0: 1790 | version "2.0.0" 1791 | resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" 1792 | integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== 1793 | 1794 | workerpool@6.2.1: 1795 | version "6.2.1" 1796 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" 1797 | integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== 1798 | 1799 | wrap-ansi@^7.0.0: 1800 | version "7.0.0" 1801 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1802 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1803 | dependencies: 1804 | ansi-styles "^4.0.0" 1805 | string-width "^4.1.0" 1806 | strip-ansi "^6.0.0" 1807 | 1808 | wrappy@1: 1809 | version "1.0.2" 1810 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1811 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1812 | 1813 | ws@~8.2.3: 1814 | version "8.2.3" 1815 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" 1816 | integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== 1817 | 1818 | y18n@^5.0.5: 1819 | version "5.0.8" 1820 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 1821 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 1822 | 1823 | yargs-parser@20.2.4: 1824 | version "20.2.4" 1825 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 1826 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 1827 | 1828 | yargs-parser@^20.2.2: 1829 | version "20.2.9" 1830 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 1831 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 1832 | 1833 | yargs-unparser@2.0.0: 1834 | version "2.0.0" 1835 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 1836 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 1837 | dependencies: 1838 | camelcase "^6.0.0" 1839 | decamelize "^4.0.0" 1840 | flat "^5.0.2" 1841 | is-plain-obj "^2.1.0" 1842 | 1843 | yargs@16.2.0, yargs@^16.1.1: 1844 | version "16.2.0" 1845 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 1846 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 1847 | dependencies: 1848 | cliui "^7.0.2" 1849 | escalade "^3.1.1" 1850 | get-caller-file "^2.0.5" 1851 | require-directory "^2.1.1" 1852 | string-width "^4.2.0" 1853 | y18n "^5.0.5" 1854 | yargs-parser "^20.2.2" 1855 | 1856 | yocto-queue@^0.1.0: 1857 | version "0.1.0" 1858 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1859 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1860 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "ktor-io" 2 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/BitOperations.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public inline val Short.highByte: Byte get() = (toInt() ushr 8).toByte() 4 | 5 | public inline val Short.lowByte: Byte get() = (toInt() and 0xff).toByte() 6 | 7 | public inline val Int.highShort: Short get() = (this ushr 16).toShort() 8 | 9 | public inline val Int.lowShort: Short get() = (this and 0xffff).toShort() 10 | 11 | public inline val Long.highInt: Int get() = (this ushr 32).toInt() 12 | 13 | public inline val Long.lowInt: Int get() = (this and 0xffffffffL).toInt() 14 | 15 | internal fun Short(highByte: Byte, lowByte: Byte): Short = 16 | ((highByte.toInt() shl 8) or (lowByte.toInt() and 0xff)).toShort() 17 | 18 | internal fun Int(highShort: Short, lowShort: Short): Int = 19 | (highShort.toInt() shl 16) or (lowShort.toInt() and 0xffff) 20 | 21 | internal fun Long(highInt: Int, lowInt: Int): Long = 22 | (highInt.toLong() shl 32) or (lowInt.toLong() and 0xffffffffL) 23 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/Buffer.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import kotlin.math.max 4 | import kotlin.math.min 5 | 6 | /** 7 | * The [Buffer] class represents a mutable sequence of bytes in memory. 8 | * 9 | * The buffer is not thread-safe by default. 10 | */ 11 | public interface Buffer : Closeable { 12 | /** 13 | * The number of bytes can be stored in the buffer. Upper bound for write operations. 14 | */ 15 | public val capacity: Int 16 | 17 | /** 18 | * The index in buffer for the read operation. 19 | * 20 | * Should be between 0 and [writeIndex] 21 | */ 22 | public var readIndex: Int 23 | 24 | /** 25 | * The index in buffer for the write operation. 26 | * 27 | * Should be between the [readIndex] and [capacity]. 28 | */ 29 | public var writeIndex: Int 30 | 31 | /** 32 | * Reads [Byte] at specific [index]. 33 | * 34 | * The operation doesn't modify [readIndex] or [writeIndex]. 35 | * 36 | * @throws IndexOutOfBoundsException if [index + 1] is greater [capacity]. 37 | */ 38 | public fun getByteAt(index: Int): Byte 39 | 40 | /** 41 | * Writes [Byte] at specific [index]. 42 | * 43 | * The operation doesn't modify [readIndex] or [writeIndex]. 44 | * 45 | * @throws IndexOutOfBoundsException if [index + 1] is greater than [capacity]. 46 | */ 47 | public fun setByteAt(index: Int, value: Byte) 48 | 49 | /** 50 | * Reads [Byte] from the buffer at [readIndex]. 51 | * 52 | * @throws IndexOutOfBoundsException if [availableForRead] < 1. 53 | */ 54 | public fun readByte(): Byte { 55 | ensureCanRead(1) 56 | return getByteAt(readIndex++) 57 | } 58 | 59 | /** 60 | * Writes [Byte] to the buffer at [writeIndex]. 61 | * 62 | * @throws IndexOutOfBoundsException if [availableForWrite] < 1. 63 | */ 64 | public fun writeByte(value: Byte) { 65 | ensureCanWrite(1) 66 | setByteAt(writeIndex++, value) 67 | } 68 | 69 | /** 70 | * Reads [Boolean] at specific [index]. 71 | * 72 | * The operation doesn't modify [readIndex] or [writeIndex]. 73 | * 74 | * @throws IndexOutOfBoundsException if [index + 1] is greater [capacity]. 75 | */ 76 | public fun getBooleanAt(index: Int): Boolean = getByteAt(index) != 0.toByte() 77 | 78 | /** 79 | * Writes [Boolean] at specific [index]. 80 | * 81 | * The operation doesn't modify [readIndex] or [writeIndex]. 82 | * 83 | * @throws IndexOutOfBoundsException if [index + 1] is greater than [capacity]. 84 | */ 85 | public fun setBooleanAt(index: Int, value: Boolean) { 86 | setByteAt(index, if (value) 1.toByte() else 0.toByte()) 87 | } 88 | 89 | /** 90 | * Read boolean from the buffer at [readIndex]. 91 | * 92 | * @throws IndexOutOfBoundsException if [availableForRead] < 1. 93 | */ 94 | public fun readBoolean(): Boolean = getBooleanAt(readIndex++) 95 | 96 | /** 97 | * Write boolean to the buffer at [writeIndex]. 98 | * 99 | * @throws IndexOutOfBoundsException if [availableForWrite] < 1. 100 | */ 101 | public fun writeBoolean(value: Boolean) { 102 | ensureCanWrite(1) 103 | setBooleanAt(writeIndex++, value) 104 | } 105 | 106 | /** 107 | * Reads [Short] at specific [index]. 108 | * 109 | * The operation doesn't modify [readIndex] or [writeIndex]. 110 | * 111 | * @throws IndexOutOfBoundsException if [index + 2] is greater [capacity]. 112 | */ 113 | public fun getShortAt(index: Int): Short { 114 | ensureCanRead(index, 2) 115 | 116 | val byte1 = getByteAt(index) 117 | val byte2 = getByteAt(index + 1) 118 | return Short(byte1, byte2) 119 | } 120 | 121 | /** 122 | * Writes [Short] at specific [index]. 123 | * 124 | * The operation doesn't modify [readIndex] or [writeIndex]. 125 | * 126 | * @throws IndexOutOfBoundsException if [index + 2] is greater than [capacity]. 127 | */ 128 | public fun setShortAt(index: Int, value: Short) { 129 | ensureCanWrite(index, 2) 130 | 131 | setByteAt(index, value.highByte) 132 | setByteAt(index + 1, value.lowByte) 133 | } 134 | 135 | /** 136 | * Writes [Short] to the buffer at [writeIndex]. 137 | * 138 | * @throws IndexOutOfBoundsException if [availableForWrite] < 2. 139 | */ 140 | public fun writeShort(value: Short) { 141 | ensureCanWrite(2) 142 | 143 | setShortAt(writeIndex, value) 144 | writeIndex += 2 145 | } 146 | 147 | /** 148 | * Reads [Short] from the buffer at [readIndex]. 149 | * 150 | * @throws IndexOutOfBoundsException if [availableForRead] < 2. 151 | */ 152 | public fun readShort(): Short { 153 | ensureCanRead(2) 154 | 155 | val result = getShortAt(readIndex) 156 | readIndex += 2 157 | return result 158 | } 159 | 160 | /** 161 | * Reads [Int] at specific [index]. 162 | * 163 | * The operation doesn't modify [readIndex] or [writeIndex]. 164 | * 165 | * @throws IndexOutOfBoundsException if [index + 4] is greater than [capacity]. 166 | */ 167 | public fun getIntAt(index: Int): Int { 168 | ensureCanRead(index, 4) 169 | 170 | val highShort = getShortAt(index) 171 | val lowShort = getShortAt(index + 2) 172 | return Int(highShort, lowShort) 173 | } 174 | 175 | /** 176 | * Writes [Int] at specific [index]. 177 | * 178 | * The operation doesn't modify [readIndex] or [writeIndex]. 179 | * 180 | * @throws IndexOutOfBoundsException if [index + 4] is greater than [capacity]. 181 | */ 182 | public fun setIntAt(index: Int, value: Int) { 183 | ensureCanWrite(index, 4) 184 | 185 | setShortAt(index, value.highShort) 186 | setShortAt(index + 2, value.lowShort) 187 | } 188 | 189 | /** 190 | * Reads [Int] from the buffer at [readIndex]. 191 | * 192 | * @throws IndexOutOfBoundsException if [availableForRead] < 4. 193 | */ 194 | public fun readInt(): Int { 195 | ensureCanRead(4) 196 | 197 | val result = getIntAt(readIndex) 198 | readIndex += 4 199 | return result 200 | } 201 | 202 | /** 203 | * Writes [Int] to the buffer at [writeIndex]. 204 | * 205 | * @throws IndexOutOfBoundsException if [availableForWrite] < 4. 206 | */ 207 | public fun writeInt(value: Int) { 208 | ensureCanWrite(4) 209 | 210 | setIntAt(writeIndex, value) 211 | writeIndex += 4 212 | } 213 | 214 | /** 215 | * Reads [Long] at specific [index]. 216 | * 217 | * The operation doesn't modify [readIndex] or [writeIndex]. 218 | * 219 | * @throws IndexOutOfBoundsException if [index + 8] is greater than [capacity]. 220 | */ 221 | public fun getLongAt(index: Int): Long { 222 | ensureCanRead(index, 8) 223 | 224 | val highInt = getIntAt(index) 225 | val lowInt = getIntAt(index + 4) 226 | return Long(highInt, lowInt) 227 | } 228 | 229 | /** 230 | * Writes [Long] at specific [index]. 231 | * 232 | * The operation doesn't modify [readIndex] or [writeIndex]. 233 | * 234 | * @throws IndexOutOfBoundsException if [index + 8] is greater than [capacity] or not enough space available. 235 | */ 236 | public fun setLongAt(index: Int, value: Long) { 237 | ensureCanWrite(index, 8) 238 | 239 | setIntAt(index, value.highInt) 240 | setIntAt(index + 4, value.lowInt) 241 | } 242 | 243 | /** 244 | * Reads [Long] from the buffer at [readIndex]. 245 | * 246 | * @throws IndexOutOfBoundsException if [availableForRead] < 8. 247 | */ 248 | public fun readLong(): Long { 249 | ensureCanRead(8) 250 | 251 | val result = getLongAt(readIndex) 252 | readIndex += 8 253 | return result 254 | } 255 | 256 | /** 257 | * Writes [Long] to the buffer at [writeIndex]. 258 | * 259 | * @throws IndexOutOfBoundsException if [availableForWrite] < 8. 260 | */ 261 | public fun writeLong(value: Long) { 262 | ensureCanWrite(8) 263 | 264 | setLongAt(writeIndex, value) 265 | writeIndex += 8 266 | } 267 | 268 | /** 269 | * Writes as many bytes as possible from the [value] at specific [index]. 270 | * 271 | * The [value.readIndex] increased by amount of copied bytes. 272 | * 273 | * @return Number of written bytes: `min(availableForWrite, buffer.availableForRead)` 274 | */ 275 | public fun copyFromBufferAt(index: Int, value: Buffer): Int { 276 | val count = min(capacity - index, value.availableForRead) 277 | for (currentIndex in 0 until count) { 278 | setByteAt(index + currentIndex, value.getByteAt(value.readIndex++)) 279 | } 280 | 281 | return max(count, 0) 282 | } 283 | 284 | /** 285 | * Write [value] to the current buffer. The implementation depends on the actual buffer implementation. 286 | */ 287 | public fun copyFromBuffer(value: Buffer): Int { 288 | val count = copyFromBufferAt(writeIndex, value) 289 | writeIndex += count 290 | return count 291 | } 292 | 293 | /** 294 | * Copy as much as possible bytes from the current buffer to the [destination] between [startIndex] and [endIndex]. 295 | * 296 | * This operation increase [readIndex] by the number of copied bytes. 297 | * 298 | * @return Number of copied bytes: `min(availableForRead, endPosition - startPosition)` 299 | */ 300 | public fun copyToByteArrayAt( 301 | index: Int, 302 | destination: ByteArray, 303 | startIndex: Int = 0, 304 | endIndex: Int = destination.size 305 | ): Int { 306 | val count = min(endIndex - startIndex, capacity - index) 307 | for (offset in 0 until count) { 308 | destination[startIndex + offset] = getByteAt(index + offset) 309 | } 310 | 311 | return max(count, 0) 312 | } 313 | 314 | /** 315 | * Copy as much as possible bytes from the current buffer to the [destination] between [startIndex] and [endIndex]. 316 | * 317 | * This operation increase [readIndex] by the number of copied bytes. 318 | * 319 | * @return Number of copied bytes: `min(availableForRead, endPosition - startPosition)` 320 | */ 321 | public fun copyToByteArray( 322 | destination: ByteArray, 323 | startIndex: Int = 0, 324 | endIndex: Int = destination.size 325 | ): Int { 326 | val count = min(endIndex - startIndex, availableForRead) 327 | if (count < 0) return 0 328 | 329 | val result = copyToByteArrayAt(readIndex, destination, startIndex, startIndex + count) 330 | readIndex += result 331 | return result 332 | } 333 | 334 | /** 335 | * Copy all bytes from [value] between [startIndex] and [endIndex] to the buffer at specific [index]. 336 | * 337 | * The operation doesn't modify [readIndex] or [writeIndex]. 338 | * 339 | * @return Number of written bytes: `min(availableForWrite, endPosition - startPosition)` 340 | * @throws IndexOutOfBoundsException if [index] is greater or equal [capacity]. 341 | */ 342 | public fun copyFromByteArrayAt( 343 | index: Int, 344 | value: ByteArray, 345 | startIndex: Int = 0, 346 | endIndex: Int = value.size 347 | ): Int { 348 | val count = min(endIndex - startIndex, capacity - index) 349 | for (offset in 0 until count) { 350 | setByteAt(index + offset, value[startIndex + offset]) 351 | } 352 | 353 | return max(count, 0) 354 | } 355 | 356 | /** 357 | * Copy values from byte array to the buffer at [writeIndex] between [startIndex] and [endIndex]. 358 | * 359 | * @ return number of copied bytes = `min(availableForWrite, endIndex - startIndex)` 360 | */ 361 | public fun copyFromByteArray(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size): Int { 362 | val result = copyFromByteArrayAt(writeIndex, value, startIndex, endIndex) 363 | writeIndex += result 364 | return result 365 | } 366 | 367 | /** 368 | * Move all bytes in range [readIndex], [writeIndex] to range [0] and [writeIndex - readIndex] and modifies the 369 | * [readIndex] and [writeIndex] accordingly. 370 | */ 371 | public fun compact() { 372 | if (readIndex == 0) return 373 | 374 | if (readIndex == writeIndex) { 375 | readIndex = 0 376 | writeIndex = 0 377 | return 378 | } 379 | 380 | val count = writeIndex - readIndex 381 | for (index in 0 until count) { 382 | setByteAt(index, getByteAt(readIndex + index)) 383 | } 384 | 385 | readIndex = 0 386 | writeIndex = count 387 | } 388 | 389 | /** 390 | * Release [Buffer] back to pool if necessary. 391 | */ 392 | override fun close() { 393 | } 394 | 395 | public companion object { 396 | /** 397 | * The buffer with zero capacity. 398 | */ 399 | public val Empty: Buffer = object : Buffer { 400 | override val capacity: Int 401 | get() = 0 402 | 403 | override var readIndex: Int 404 | get() = 0 405 | set(value) { 406 | require(value == 0) { "Can't modify default empty buffer" } 407 | } 408 | 409 | override var writeIndex: Int 410 | get() = 0 411 | set(value) { 412 | require(value == 0) { "Can't modify default empty buffer" } 413 | } 414 | 415 | override fun getByteAt(index: Int): Byte { 416 | throw IndexOutOfBoundsException("Can't read from empty buffer") 417 | } 418 | 419 | override fun setByteAt(index: Int, value: Byte) { 420 | throw IndexOutOfBoundsException("Can't write to empty buffer") 421 | } 422 | } 423 | } 424 | } 425 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/BufferOperations.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public val Buffer.isEmpty: Boolean get() = availableForRead == 0 4 | public val Buffer.isNotEmpty: Boolean get() = !isEmpty 5 | 6 | public val Buffer.isFull: Boolean get() = availableForWrite == 0 7 | public val Buffer.isNotFull: Boolean get() = !isFull 8 | 9 | public val Buffer.availableForRead: Int get() = writeIndex - readIndex 10 | public val Buffer.availableForWrite: Int get() = capacity - writeIndex 11 | 12 | internal fun Buffer.reset() { 13 | readIndex = 0 14 | writeIndex = 0 15 | } 16 | 17 | public operator fun Buffer.get(index: Int): Byte = getByteAt(index) 18 | 19 | public operator fun Buffer.set(index: Int, value: Byte) { 20 | setByteAt(index, value) 21 | } 22 | 23 | /** 24 | * Check if the Buffer has [count] bytes to read. 25 | * 26 | * @throws IndexOutOfBoundsException if the [count] is greater [availableForRead]. 27 | */ 28 | public fun Buffer.ensureCanRead(count: Int) { 29 | if (availableForRead < count) { 30 | throw IndexOutOfBoundsException("Can't read $count bytes. Available: $availableForRead.") 31 | } 32 | } 33 | 34 | internal fun Buffer.ensureCanRead(index: Int, count: Int) { 35 | if (index + count > capacity) { 36 | throw IndexOutOfBoundsException("Can't read $count bytes at index $index. Capacity: $capacity.") 37 | } 38 | } 39 | 40 | 41 | /** 42 | * Check if the Buffer has space to write [count] bytes. 43 | * 44 | * @throws IndexOutOfBoundsException if the [count] is greater [availableForWrite]. 45 | */ 46 | public fun Buffer.ensureCanWrite(count: Int) { 47 | if (availableForWrite < count) { 48 | throw IndexOutOfBoundsException("Can't write $count bytes. Available space: $availableForWrite.") 49 | } 50 | } 51 | 52 | internal fun Buffer.ensureCanWrite(index: Int, count: Int) { 53 | if (index + count > capacity) { 54 | throw IndexOutOfBoundsException("Can't write $count bytes at index $index. Capacity: $capacity.") 55 | } 56 | } -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/BufferedBytesDestination.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public class BufferedBytesDestination( 4 | private val delegate: BytesDestination, 5 | bufferSize: Int = DEFAULT_BUFFER_SIZE 6 | ) : BytesDestination() { 7 | 8 | private val buffer: Buffer 9 | 10 | init { 11 | buffer = if (bufferSize == DEFAULT_BUFFER_SIZE) { 12 | ByteArrayBufferPool.Default.borrow() 13 | } else { 14 | ByteArrayBuffer(bufferSize) 15 | } 16 | } 17 | 18 | override val closedCause: Throwable? 19 | get() = delegate.closedCause 20 | 21 | override fun canWrite(): Boolean = delegate.canWrite() 22 | 23 | override fun write(buffer: Buffer): Int { 24 | closedCause?.let { throw it } 25 | 26 | return this.buffer.copyFromBuffer(buffer) 27 | } 28 | 29 | override suspend fun flush() { 30 | closedCause?.let { throw it } 31 | 32 | while (buffer.isNotEmpty) { 33 | delegate.write(buffer) 34 | delegate.awaitFreeSpace() 35 | } 36 | 37 | buffer.reset() 38 | delegate.flush() 39 | } 40 | 41 | override suspend fun awaitFreeSpace() { 42 | closedCause?.let { throw it } 43 | 44 | while (buffer.isFull) { 45 | delegate.awaitFreeSpace() 46 | delegate.write(buffer) 47 | buffer.compact() 48 | } 49 | } 50 | 51 | override fun close(cause: Throwable?) { 52 | buffer.close() 53 | delegate.close(cause) 54 | } 55 | 56 | override fun close() { 57 | delegate.close() 58 | } 59 | 60 | public suspend fun writeByte(value: Byte) { 61 | closedCause?.let { throw it } 62 | 63 | if (buffer.isNotFull) { 64 | buffer.writeByte(value) 65 | } else { 66 | awaitFreeSpace() 67 | buffer.writeByte(value) 68 | } 69 | 70 | flushIfFull() 71 | } 72 | 73 | public suspend fun writeShort(value: Short) { 74 | closedCause?.let { throw it } 75 | 76 | if (buffer.availableForWrite >= 2) { 77 | buffer.writeShort(value) 78 | } else { 79 | writeByte(value.highByte) 80 | writeByte(value.lowByte) 81 | } 82 | 83 | flushIfFull() 84 | } 85 | 86 | public suspend fun writeInt(value: Int) { 87 | closedCause?.let { throw it } 88 | 89 | if (buffer.availableForWrite >= 4) { 90 | buffer.writeInt(value) 91 | } else { 92 | writeShort(value.highShort) 93 | writeShort(value.lowShort) 94 | } 95 | 96 | flushIfFull() 97 | } 98 | 99 | public suspend fun writeLong(value: Long) { 100 | closedCause?.let { throw it } 101 | 102 | if (buffer.availableForWrite >= 8) { 103 | buffer.writeLong(value) 104 | } else { 105 | writeInt(value.highInt) 106 | writeInt(value.lowInt) 107 | } 108 | 109 | flushIfFull() 110 | } 111 | 112 | private suspend fun flushIfFull() { 113 | if (buffer.isFull) { 114 | flush() 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/BufferedBytesSource.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public class BufferedBytesSource( 4 | private val delegate: BytesSource 5 | ) : BytesSource() { 6 | 7 | private var buffer: Buffer 8 | 9 | init { 10 | buffer = delegate.read() 11 | } 12 | 13 | override val closedCause: Throwable? 14 | get() = delegate.closedCause 15 | 16 | override fun canRead(): Boolean { 17 | return delegate.canRead() || buffer.isNotEmpty 18 | } 19 | 20 | override fun read(): Buffer { 21 | closedCause?.let { throw it } 22 | 23 | if (buffer.isNotEmpty) { 24 | return buffer 25 | } 26 | 27 | buffer.close() 28 | buffer = delegate.read() 29 | return buffer 30 | } 31 | 32 | override suspend fun awaitContent() { 33 | closedCause?.let { throw it } 34 | 35 | if (buffer.isNotEmpty) return 36 | delegate.awaitContent() 37 | } 38 | 39 | override fun cancel(cause: Throwable) { 40 | delegate.cancel(cause) 41 | } 42 | 43 | public suspend fun readByte(): Byte { 44 | closedCause?.let { throw it } 45 | 46 | while (buffer.isEmpty) { 47 | awaitContent() 48 | read() 49 | } 50 | return buffer.readByte() 51 | } 52 | 53 | public suspend fun readShort(): Short { 54 | closedCause?.let { throw it } 55 | 56 | if (buffer.availableForRead >= 2) { 57 | return buffer.readShort() 58 | } 59 | return Short(readByte(), readByte()) 60 | } 61 | 62 | public suspend fun readInt(): Int { 63 | closedCause?.let { throw it } 64 | 65 | if (buffer.availableForRead >= 4) { 66 | return buffer.readInt() 67 | } 68 | return Int(readShort(), readShort()) 69 | } 70 | 71 | public suspend fun readLong(): Long { 72 | closedCause?.let { throw it } 73 | 74 | if (buffer.availableForRead >= 8) { 75 | return buffer.readLong() 76 | } 77 | return Long(readInt(), readInt()) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/ByteArrayBuffer.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import kotlin.math.min 4 | 5 | public const val DEFAULT_POOL_CAPACITY: Int = 2000 6 | public const val DEFAULT_BUFFER_SIZE: Int = 1024 * 16 7 | 8 | public class ByteArrayBuffer( 9 | array: ByteArray, 10 | readIndex: Int = 0, 11 | writeIndex: Int = array.size, 12 | /** 13 | * The pool used for allocation of the [array]. 14 | */ 15 | public val pool: ObjectPool = ByteArrayPool.Empty 16 | ) : Buffer { 17 | 18 | /** 19 | * Creates buffer of fixed [capacity]. 20 | */ 21 | public constructor(capacity: Int) : this(ByteArray(capacity), readIndex = 0, writeIndex = 0) 22 | 23 | public constructor(pool: ObjectPool = ByteArrayPool.Empty) : this( 24 | pool.borrow(), 25 | readIndex = 0, 26 | writeIndex = 0, 27 | pool = pool 28 | ) 29 | 30 | /** 31 | * Provides access to underlying byte array. 32 | * 33 | * Please note, all changes of the array will be reflected in the buffer. 34 | */ 35 | @Suppress("CanBePrimaryConstructorProperty") 36 | public var array: ByteArray = array 37 | private set 38 | 39 | override val capacity: Int 40 | get() = array.size 41 | 42 | override var readIndex: Int = readIndex 43 | set(value) { 44 | if (value < 0 || value > writeIndex) { 45 | throw IndexOutOfBoundsException("readIndex($value) must be >= 0 and < writeIndex: $writeIndex") 46 | } 47 | field = value 48 | } 49 | 50 | override var writeIndex: Int = writeIndex 51 | set(value) { 52 | if (value < 0 || value > capacity) { 53 | throw IndexOutOfBoundsException("Write index $value is out of bounds: $capacity") 54 | } 55 | 56 | field = value 57 | } 58 | 59 | override fun getByteAt(index: Int): Byte { 60 | ensureCanRead(index, 1, writeIndex) 61 | return array[index] 62 | } 63 | 64 | override fun setByteAt(index: Int, value: Byte) { 65 | ensureCanWrite(index, 1, capacity) 66 | array[index] = value 67 | } 68 | 69 | override fun copyFromBufferAt(index: Int, value: Buffer): Int { 70 | return value.copyToByteArray(array, index, capacity) 71 | } 72 | 73 | override fun copyToByteArrayAt(index: Int, destination: ByteArray, startIndex: Int, endIndex: Int): Int { 74 | require(startIndex >= 0) { "startIndex($startIndex) must be >= 0" } 75 | require(endIndex <= destination.size) { "endIndex($endIndex) must be <= destination.size(${destination.size})" } 76 | require(startIndex <= endIndex) { "startIndex($startIndex) must be <= endIndex($endIndex)" } 77 | require(index < capacity) { "index($index) must be < capacity($capacity)" } 78 | 79 | val count = min(capacity - index, endIndex - startIndex) 80 | 81 | array.copyInto(destination, startIndex, index, index + count) 82 | readIndex += count 83 | return count 84 | } 85 | 86 | override fun copyToByteArray(destination: ByteArray, startIndex: Int, endIndex: Int): Int { 87 | require(startIndex >= 0) { "startIndex($startIndex) must be >= 0" } 88 | require(endIndex <= destination.size) { "endIndex($endIndex) must be <= destination.size(${destination.size})" } 89 | require(startIndex <= endIndex) { "startIndex($startIndex) must be <= endIndex($endIndex)" } 90 | 91 | val count = min(availableForRead, endIndex - startIndex) 92 | 93 | array.copyInto(destination, startIndex, readIndex, readIndex + count) 94 | readIndex += count 95 | return count 96 | } 97 | 98 | override fun copyFromByteArrayAt(index: Int, value: ByteArray, startIndex: Int, endIndex: Int): Int { 99 | require(startIndex >= 0) { "startPosition($startIndex) must be >= 0" } 100 | require(endIndex <= value.size) { "endPosition($endIndex) must be <= value.size(${value.size})" } 101 | require(startIndex <= endIndex) { "startPosition($startIndex) must be <= endPosition($endIndex)" } 102 | 103 | val count = min(capacity - index, endIndex - startIndex) 104 | value.copyInto(array, index, startIndex, startIndex + count) 105 | return count 106 | } 107 | 108 | /** 109 | * Returns this buffer back to the pool. 110 | */ 111 | override fun close() { 112 | pool.recycle(array) 113 | } 114 | 115 | override fun compact() { 116 | if (readIndex == 0) return 117 | array.copyInto(array, 0, readIndex, writeIndex) 118 | writeIndex = availableForRead 119 | readIndex = 0 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/ByteArrayBufferPool.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public class ByteArrayBufferPool( 4 | capacity: Int = DEFAULT_POOL_CAPACITY, 5 | public val arrayPool: ObjectPool = ByteArrayPool.Default, 6 | ) : DefaultPool(capacity) { 7 | 8 | override fun produceInstance(): ByteArrayBuffer = ByteArrayBuffer(arrayPool) 9 | 10 | override fun clearInstance(instance: ByteArrayBuffer): ByteArrayBuffer { 11 | instance.reset() 12 | return instance 13 | } 14 | 15 | public companion object { 16 | public val Default: ObjectPool = ByteArrayBufferPool() 17 | 18 | public val Empty: ObjectPool = ByteArrayBufferPool( 19 | capacity = 0, 20 | arrayPool = ByteArrayPool.Empty 21 | ) 22 | } 23 | } 24 | 25 | public class ByteArrayPool( 26 | private val size: Int = DEFAULT_BUFFER_SIZE, 27 | capacity: Int = DEFAULT_POOL_CAPACITY, 28 | ) : DefaultPool(capacity) { 29 | 30 | override fun produceInstance(): ByteArray = ByteArray(size) 31 | 32 | override fun clearInstance(instance: ByteArray): ByteArray { 33 | instance.fill(0) 34 | return instance 35 | } 36 | 37 | public companion object { 38 | public val Default: ObjectPool = ByteArrayPool() 39 | 40 | public val Empty: ObjectPool = ByteArrayPool(capacity = 0) 41 | } 42 | } -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/ByteArrayOperations.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | /** 4 | * Loads [Short] from the byte array at the specified [index]. 5 | * 6 | * @throws IndexOutOfBoundsException if there are not enough bytes in the array. 7 | */ 8 | public fun ByteArray.getShortAt(index: Int): Short { 9 | ensureCanRead(index, 2, size) 10 | return Short(this[index], this[index + 1]) 11 | } 12 | 13 | /** 14 | * Loads [Int] from the byte array at the specified [index]. 15 | * 16 | * @throws IndexOutOfBoundsException if there are not enough bytes in the array. 17 | */ 18 | public fun ByteArray.getIntAt(index: Int): Int { 19 | ensureCanRead(index, 4, size) 20 | 21 | return Int(getShortAt(index), getShortAt(index + 2)) 22 | } 23 | 24 | /** 25 | * Loads [Long] from the byte array at the specified [index]. 26 | * 27 | * @throws IndexOutOfBoundsException if there are not enough bytes in the array. 28 | */ 29 | public fun ByteArray.getLongAt(index: Int): Long { 30 | ensureCanRead(index, 8, size) 31 | return Long(getIntAt(index), getIntAt(index + 4)) 32 | } 33 | 34 | /** 35 | * Stores [value] to the byte array at the specified [index]. 36 | * 37 | * @throws IndexOutOfBoundsException if there are not enough bytes in the array. 38 | */ 39 | public fun ByteArray.setShortAt(index: Int, value: Short): ByteArray { 40 | ensureCanWrite(index, 2, size) 41 | 42 | this[index] = value.highByte 43 | this[index + 1] = value.lowByte 44 | 45 | return this 46 | } 47 | 48 | /** 49 | * Stores [value] to the byte array at the specified [index]. 50 | * 51 | * @throws IndexOutOfBoundsException if there are not enough bytes in the array. 52 | */ 53 | public fun ByteArray.setIntAt(index: Int, value: Int): ByteArray { 54 | ensureCanWrite(index, 4, size) 55 | 56 | setShortAt(index, value.highShort) 57 | setShortAt(index + 2, value.lowShort) 58 | 59 | return this 60 | } 61 | 62 | /** 63 | * Stores [value] to the byte array at the specified [index]. 64 | * 65 | * @throws IndexOutOfBoundsException if there are not enough bytes in the array. 66 | */ 67 | public fun ByteArray.setLongAt(index: Int, value: Long): ByteArray { 68 | ensureCanWrite(index, 8, size) 69 | 70 | setIntAt(index, value.highInt) 71 | setIntAt(index + 4, value.lowInt) 72 | 73 | return this 74 | } 75 | 76 | internal fun ensureCanRead(index: Int, count: Int, capacity: Int) { 77 | if (index + count > capacity) { 78 | throw IndexOutOfBoundsException("Can't read $count bytes at index $index from array of size $capacity") 79 | } 80 | } 81 | 82 | internal fun ensureCanWrite(index: Int, count: Int, capacity: Int) { 83 | if (index + count > capacity) { 84 | throw IndexOutOfBoundsException("Can't write $count bytes at index $index to array of size $capacity") 85 | } 86 | } 87 | 88 | private fun Byte.asInt(): Int = toInt() and 0xFF -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/ByteOperations.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public infix fun Byte.and(other: Byte): Byte = ((toInt() and 0xFF) and (other.toInt() and 0xFF)).toByte() 4 | 5 | public infix fun Byte.or(other: Byte): Byte = ((toInt() and 0xFF) and (other.toInt() and 0xFF)).toByte() 6 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/BytesDestination.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public abstract class BytesDestination : Closeable { 4 | public abstract val closedCause: Throwable? 5 | public abstract fun canWrite(): Boolean 6 | 7 | public abstract fun write(buffer: Buffer): Int 8 | public abstract suspend fun flush() 9 | public abstract suspend fun awaitFreeSpace() 10 | 11 | public abstract fun close(cause: Throwable? = null) 12 | } 13 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/BytesSource.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public abstract class BytesSource { 4 | public abstract val closedCause: Throwable? 5 | public abstract fun canRead(): Boolean 6 | 7 | public abstract fun read(): Buffer 8 | public abstract suspend fun awaitContent() 9 | 10 | public abstract fun cancel(cause: Throwable = IOException("FooBar")) 11 | } 12 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/Closeable.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public expect interface Closeable { 4 | public fun close() 5 | } 6 | 7 | public inline fun C.use(block: (C) -> R): R { 8 | var closed = false 9 | 10 | return try { 11 | block(this) 12 | } catch (first: Throwable) { 13 | try { 14 | closed = true 15 | close() 16 | } catch (second: Throwable) { 17 | first.addSuppressedInternal(second) 18 | } 19 | 20 | throw first 21 | } finally { 22 | if (!closed) { 23 | close() 24 | } 25 | } 26 | } 27 | 28 | @PublishedApi 29 | internal expect fun Throwable.addSuppressedInternal(other: Throwable) 30 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/DefaultPool.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | /** 4 | * Default object pool implementation. 5 | */ 6 | public expect abstract class DefaultPool(capacity: Int) : ObjectPool { 7 | /** 8 | * Pool capacity. 9 | */ 10 | final override val capacity: Int 11 | 12 | /** 13 | * Creates a new instance of [T] 14 | */ 15 | protected abstract fun produceInstance(): T 16 | 17 | /** 18 | * Dispose [instance] and release its resources 19 | */ 20 | protected open fun disposeInstance(instance: T) 21 | 22 | /** 23 | * Clear [instance]'s state before reuse: reset pointers, counters and so on 24 | */ 25 | protected open fun clearInstance(instance: T): T 26 | 27 | /** 28 | * Validate [instance] of [T]. Could verify that the object has been borrowed from this pool 29 | */ 30 | protected open fun validateInstance(instance: T) 31 | 32 | final override fun borrow(): T 33 | 34 | final override fun recycle(instance: T) 35 | 36 | final override fun dispose() 37 | } 38 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/Errors.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public expect open class IOException(message: String, cause: Throwable?) : Exception { 4 | public constructor(message: String) 5 | } 6 | 7 | public expect open class EOFException(message: String) : IOException 8 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/NoPoolImpl.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | /** 4 | * A pool implementation of zero capacity that always creates new instances 5 | */ 6 | public abstract class NoPoolImpl : ObjectPool { 7 | override val capacity: Int 8 | get() = 0 9 | 10 | override fun recycle(instance: T) { 11 | } 12 | 13 | override fun dispose() { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/commonMain/kotlin/io/ktor/io/Pool.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public interface ObjectPool : Closeable { 4 | /** 5 | * Pool capacity 6 | */ 7 | public val capacity: Int 8 | 9 | /** 10 | * borrow an instance. Pool can recycle an old instance or create a new one 11 | */ 12 | public fun borrow(): T 13 | 14 | /** 15 | * Recycle an instance. Should be recycled what was borrowed before otherwise could fail 16 | */ 17 | public fun recycle(instance: T) 18 | 19 | /** 20 | * Dispose the whole pool. None of borrowed objects could be used after the pool gets disposed 21 | * otherwise it can result in undefined behaviour 22 | */ 23 | public fun dispose() 24 | 25 | /** 26 | * Does pool dispose 27 | */ 28 | override fun close() { 29 | dispose() 30 | } 31 | } 32 | 33 | /** 34 | * Borrows and instance of [T] from the pool, invokes [block] with it and finally recycles it 35 | */ 36 | public inline fun ObjectPool.useInstance(block: (T) -> R): R { 37 | val instance = borrow() 38 | try { 39 | return block(instance) 40 | } finally { 41 | recycle(instance) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/commonTest/kotlin/io/ktor/io/BufferTest.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertContentEquals 5 | import kotlin.test.assertEquals 6 | import kotlin.test.assertFailsWith 7 | 8 | abstract class BufferTest { 9 | 10 | abstract fun createBuffer(): Buffer 11 | 12 | @Test 13 | fun testWriteCanReadByte() { 14 | val buffer = createBuffer() 15 | buffer.writeIndex = 0 16 | 17 | buffer.writeByte(99) 18 | buffer.writeByte(-99) 19 | 20 | assertEquals(0, buffer.readIndex) 21 | assertEquals(2, buffer.writeIndex) 22 | 23 | assertEquals(99, buffer.readByte()) 24 | assertEquals(-99, buffer.readByte()) 25 | 26 | assertEquals(2, buffer.readIndex) 27 | assertEquals(2, buffer.writeIndex) 28 | } 29 | 30 | @Test 31 | fun testWriteCanReadShort() { 32 | val buffer = createBuffer() 33 | buffer.writeIndex = 0 34 | 35 | buffer.writeShort(999) 36 | buffer.writeShort(-999) 37 | 38 | assertEquals(0, buffer.readIndex) 39 | assertEquals(4, buffer.writeIndex) 40 | 41 | assertEquals(999, buffer.readShort()) 42 | assertEquals(-999, buffer.readShort()) 43 | 44 | assertEquals(4, buffer.readIndex) 45 | assertEquals(4, buffer.writeIndex) 46 | } 47 | 48 | @Test 49 | fun testWriteCanReadInt() { 50 | val buffer = createBuffer() 51 | buffer.writeIndex = 0 52 | 53 | buffer.writeInt(999_999) 54 | buffer.writeInt(-999_999) 55 | 56 | assertEquals(0, buffer.readIndex) 57 | assertEquals(8, buffer.writeIndex) 58 | 59 | assertEquals(999_999, buffer.readInt()) 60 | assertEquals(-999_999, buffer.readInt()) 61 | 62 | assertEquals(8, buffer.readIndex) 63 | assertEquals(8, buffer.writeIndex) 64 | } 65 | 66 | @Test 67 | fun testWriteCanReadLong() { 68 | val buffer = createBuffer() 69 | buffer.writeIndex = 0 70 | 71 | buffer.writeLong(9_999_999_999_999) 72 | buffer.writeLong(-9_999_999_999_999) 73 | 74 | assertEquals(0, buffer.readIndex) 75 | assertEquals(16, buffer.writeIndex) 76 | 77 | assertEquals(9_999_999_999_999, buffer.readLong()) 78 | assertEquals(-9_999_999_999_999, buffer.readLong()) 79 | 80 | assertEquals(16, buffer.readIndex) 81 | assertEquals(16, buffer.writeIndex) 82 | } 83 | 84 | @Test 85 | fun testWriteCanReadArray() { 86 | val buffer = createBuffer() 87 | buffer.writeIndex = 0 88 | 89 | val array = ByteArray(123) { it.toByte() } 90 | buffer.copyFromByteArray(array) 91 | 92 | assertEquals(0, buffer.readIndex) 93 | assertEquals(123, buffer.writeIndex) 94 | 95 | val newArray = ByteArray(123).also { buffer.copyToByteArray(it) } 96 | assertContentEquals(array, newArray) 97 | 98 | assertEquals(123, buffer.readIndex) 99 | assertEquals(123, buffer.writeIndex) 100 | } 101 | 102 | @Test 103 | fun testBoundsByte() { 104 | val buffer = createBuffer() 105 | 106 | assertFailsWith { buffer.readByte() } 107 | buffer.writeIndex = buffer.capacity - 1 108 | buffer.readIndex = buffer.writeIndex 109 | buffer.writeByte(1) 110 | assertEquals(1, buffer.readByte()) 111 | assertFailsWith { buffer.writeByte(2) } 112 | } 113 | 114 | @Test 115 | fun testBoundsShort() { 116 | val buffer = createBuffer() 117 | 118 | assertFailsWith { buffer.readShort() } 119 | buffer.writeIndex = buffer.capacity - 2 120 | buffer.readIndex = buffer.writeIndex 121 | buffer.writeShort(1) 122 | assertEquals(1, buffer.readShort()) 123 | 124 | buffer.writeIndex = buffer.capacity - 1 125 | assertFailsWith { buffer.writeShort(2) } 126 | } 127 | 128 | @Test 129 | fun testBoundsInt() { 130 | val buffer = createBuffer() 131 | 132 | assertFailsWith { buffer.readInt() } 133 | buffer.writeIndex = buffer.capacity - 4 134 | buffer.readIndex = buffer.writeIndex 135 | buffer.writeInt(1) 136 | assertEquals(1, buffer.readInt()) 137 | buffer.writeIndex = buffer.capacity - 3 138 | assertFailsWith { buffer.writeInt(2) } 139 | } 140 | 141 | @Test 142 | fun testBoundsLong() { 143 | val buffer = createBuffer() 144 | 145 | assertFailsWith { buffer.readLong() } 146 | buffer.writeIndex = buffer.capacity - 8 147 | buffer.readIndex = buffer.writeIndex 148 | buffer.writeLong(1) 149 | assertEquals(1, buffer.readLong()) 150 | buffer.writeIndex = buffer.capacity - 7 151 | assertFailsWith { buffer.writeLong(2) } 152 | } 153 | 154 | @Test 155 | fun testBoundsArray() { 156 | val buffer = createBuffer() 157 | 158 | val array = ByteArray(123) 159 | var count = buffer.copyToByteArray(array) 160 | assertEquals(0, count) 161 | 162 | buffer.writeIndex = buffer.capacity - 123 163 | buffer.readIndex = buffer.writeIndex 164 | buffer.copyFromByteArray(array) 165 | 166 | val newArray = ByteArray(123) 167 | assertContentEquals(array, newArray) 168 | buffer.writeIndex = buffer.capacity - 122 169 | count = buffer.copyFromByteArray(array) 170 | assertEquals(122, count) 171 | } 172 | 173 | 174 | @Test 175 | fun testWriteCanRead() { 176 | val buffer = createBuffer() 177 | buffer.writeIndex = 0 178 | 179 | buffer.writeByte(99) 180 | buffer.writeShort(999) 181 | buffer.writeInt(999_999) 182 | buffer.writeLong(9_999_999_999_999) 183 | 184 | val array = ByteArray(123) { it.toByte() } 185 | buffer.copyFromByteArray(array) 186 | 187 | assertEquals(0, buffer.readIndex) 188 | assertEquals(138, buffer.writeIndex) 189 | 190 | assertEquals(99, buffer.readByte()) 191 | assertEquals(999, buffer.readShort()) 192 | assertEquals(999_999, buffer.readInt()) 193 | assertEquals(9_999_999_999_999, buffer.readLong()) 194 | val newArray = ByteArray(123).also { buffer.copyToByteArray(it) } 195 | assertContentEquals(array, newArray) 196 | 197 | assertEquals(138, buffer.readIndex) 198 | assertEquals(138, buffer.writeIndex) 199 | } 200 | } -------------------------------------------------------------------------------- /src/commonTest/kotlin/io/ktor/io/BufferedBytesDestinationTest.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import io.ktor.io.utils.* 4 | import kotlin.test.Test 5 | import kotlin.test.assertEquals 6 | 7 | class BufferedBytesDestinationTest { 8 | 9 | @Test 10 | fun testWriteDoesNotFlush() { 11 | val destination = TestBytesDestination() 12 | val buffered = BufferedBytesDestination(destination, 1024) 13 | 14 | val buffer1 = ByteArrayBuffer(512) 15 | buffer1.copyFromByteArray(ByteArray(512) { it.toByte() }) 16 | 17 | val buffer2 = ByteArrayBuffer(1024) 18 | buffer2.copyFromByteArray(ByteArray(1024) { it.toByte() }) 19 | 20 | buffered.write(buffer1) 21 | buffered.write(buffer2) 22 | 23 | assertEquals(512, buffer1.readIndex) 24 | assertEquals(512, buffer2.readIndex) 25 | assertEquals(0, destination.writeCount) 26 | } 27 | 28 | @Test 29 | fun testAwaitFreeSpaceDoesNotWriteIfBufferIsNotFull() = testSuspend { 30 | val destination = TestBytesDestination() 31 | val buffered = BufferedBytesDestination(destination, 1024) 32 | 33 | val buffer1 = ByteArrayBuffer(1023) 34 | buffer1.copyFromByteArray(ByteArray(1023) { it.toByte() }) 35 | 36 | buffered.write(buffer1) 37 | buffered.awaitFreeSpace() 38 | 39 | assertEquals(0, destination.writeCount) 40 | } 41 | 42 | @Test 43 | fun testAwaitFreeSpaceWritesIfBufferIsFull() = testSuspend { 44 | val destination = TestBytesDestination() 45 | val buffered = BufferedBytesDestination(destination, 1024) 46 | 47 | val buffer1 = ByteArrayBuffer(1024) 48 | buffer1.copyFromByteArray(ByteArray(1024) { it.toByte() }) 49 | 50 | buffered.write(buffer1) 51 | buffered.awaitFreeSpace() 52 | 53 | assertEquals(1, destination.writeCount) 54 | } 55 | 56 | @Test 57 | fun testWriteByteFlushesIfBufferIsFull() = testSuspend { 58 | val destination = TestBytesDestination() 59 | val buffered = BufferedBytesDestination(destination, 1024) 60 | 61 | val buffer1 = ByteArrayBuffer(1023) 62 | buffer1.copyFromByteArray(ByteArray(1023) { it.toByte() }) 63 | 64 | buffered.write(buffer1) 65 | assertEquals(0, destination.writeCount) 66 | 67 | buffered.writeByte(1) 68 | assertEquals(1, destination.writeCount) 69 | } 70 | 71 | @Test 72 | fun testWriteByteDoesNotFlushIfBufferIsNotFull() = testSuspend { 73 | val destination = TestBytesDestination() 74 | val buffered = BufferedBytesDestination(destination, 1024) 75 | 76 | val buffer1 = ByteArrayBuffer(1022) 77 | buffer1.copyFromByteArray(ByteArray(1022) { it.toByte() }) 78 | 79 | buffered.write(buffer1) 80 | buffered.writeByte(1) 81 | assertEquals(0, destination.writeCount) 82 | } 83 | 84 | @Test 85 | fun testWriteShort() = testSuspend { 86 | val destination = TestBytesDestination() 87 | val buffered = BufferedBytesDestination(destination, 2) 88 | 89 | buffered.writeByte(1) 90 | buffered.writeShort(999) 91 | buffered.flush() 92 | 93 | assertEquals(2, destination.writeCount) 94 | 95 | val buffer1 = destination.buffers[0] 96 | val buffer2 = destination.buffers[1] 97 | buffer1.readByte() 98 | val highByte = buffer1.readByte() 99 | val lowByte = buffer2.readByte() 100 | val value = ((highByte.toInt() shl 8) or (lowByte.toInt() and 0xff)).toShort() 101 | assertEquals(999, value) 102 | } 103 | 104 | @Test 105 | fun testWriteInt() = testSuspend { 106 | val destination = TestBytesDestination() 107 | val buffered = BufferedBytesDestination(destination, 3) 108 | 109 | buffered.writeByte(1) 110 | buffered.writeInt(999999) 111 | buffered.flush() 112 | 113 | assertEquals(2, destination.writeCount) 114 | 115 | val buffer1 = destination.buffers[0] 116 | val buffer2 = destination.buffers[1] 117 | buffer1.readByte() 118 | val highShort = buffer1.readShort() 119 | val lowShort = buffer2.readShort() 120 | val value = (highShort.toInt() shl 16) or (lowShort.toInt() and 0xffff) 121 | assertEquals(999999, value) 122 | } 123 | 124 | @Test 125 | fun testWriteLong() = testSuspend { 126 | val destination = TestBytesDestination() 127 | val buffered = BufferedBytesDestination(destination, 5) 128 | 129 | buffered.writeByte(1) 130 | buffered.writeLong(999999999) 131 | buffered.flush() 132 | 133 | assertEquals(2, destination.writeCount) 134 | 135 | val buffer1 = destination.buffers[0] 136 | val buffer2 = destination.buffers[1] 137 | buffer1.readByte() 138 | val highInt = buffer1.readInt() 139 | val lowInt = buffer2.readInt() 140 | val value = (highInt.toLong() shl 32) or (lowInt.toLong() and 0xffffffffL) 141 | assertEquals(999999999, value) 142 | } 143 | } 144 | 145 | -------------------------------------------------------------------------------- /src/commonTest/kotlin/io/ktor/io/BufferedBytesSourceTest.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import io.ktor.io.utils.* 4 | import kotlin.test.* 5 | 6 | class BufferedBytesSourceTest { 7 | 8 | @Test 9 | fun testCanReadReadReturnsTrueWhenBufferHasContent() = testSuspend { 10 | val buffer1 = ByteArrayBuffer(1024) 11 | buffer1.writeByte(1) 12 | 13 | val source = TestBytesSource(buffer1) 14 | val buffered = BufferedBytesSource(source) 15 | 16 | assertTrue(buffered.canRead()) 17 | buffered.read() 18 | assertTrue(buffered.canRead()) 19 | buffered.readByte() 20 | assertFalse(buffered.canRead()) 21 | } 22 | 23 | @Test 24 | fun testReadReturnsSameBufferIfHasContent() { 25 | val buffer1 = ByteArrayBuffer(1024) 26 | buffer1.copyFromByteArray(ByteArray(123) { it.toByte() }) 27 | 28 | val buffer2 = ByteArrayBuffer(1024) 29 | buffer2.copyFromByteArray(ByteArray(123) { it.toByte() }) 30 | 31 | val source = TestBytesSource(buffer1, buffer2) 32 | val buffered = BufferedBytesSource(source) 33 | 34 | val read1 = buffered.read() 35 | repeat(buffer1.writeIndex - 1) { 36 | buffer1.readByte() 37 | } 38 | val read2 = buffered.read() 39 | assertSame(read1, read2) 40 | 41 | read2.readByte() 42 | val read3 = buffered.read() 43 | assertNotSame(read2, read3) 44 | } 45 | 46 | @Test 47 | fun testReadByteWaitsUntilHasContent() = testSuspend { 48 | val buffer1 = ByteArrayBuffer(1024) 49 | val buffer2 = ByteArrayBuffer(1024) 50 | buffer2.writeByte(1) 51 | 52 | val source = TestBytesSource(buffer1, buffer2) 53 | val buffered = BufferedBytesSource(source) 54 | 55 | val value = buffered.readByte() 56 | assertEquals(1, value) 57 | assertEquals(2, source.readCount) 58 | } 59 | 60 | @Test 61 | fun testReadShort() = testSuspend { 62 | val buffer1 = ByteArrayBuffer(1) 63 | val buffer2 = ByteArrayBuffer(1) 64 | val value: Short = 999 65 | buffer1.writeByte(value.highByte) 66 | buffer2.writeByte(value.lowByte) 67 | 68 | val source = TestBytesSource(buffer1, buffer2) 69 | val buffered = BufferedBytesSource(source) 70 | 71 | assertEquals(999, buffered.readShort()) 72 | assertEquals(2, source.readCount) 73 | } 74 | 75 | @Test 76 | fun testReadInt() = testSuspend { 77 | val buffer1 = ByteArrayBuffer(2) 78 | val buffer2 = ByteArrayBuffer(2) 79 | val value = 999 80 | buffer1.writeShort(value.highShort) 81 | buffer2.writeShort(value.lowShort) 82 | 83 | val source = TestBytesSource(buffer1, buffer2) 84 | val buffered = BufferedBytesSource(source) 85 | 86 | assertEquals(999, buffered.readInt()) 87 | assertEquals(2, source.readCount) 88 | } 89 | 90 | @Test 91 | fun testReadLong() = testSuspend { 92 | val buffer1 = ByteArrayBuffer(4) 93 | val buffer2 = ByteArrayBuffer(4) 94 | val value = 999L 95 | buffer1.writeInt(value.highInt) 96 | buffer2.writeInt(value.lowInt) 97 | 98 | val source = TestBytesSource(buffer1, buffer2) 99 | val buffered = BufferedBytesSource(source) 100 | 101 | assertEquals(999, buffered.readLong()) 102 | assertEquals(2, source.readCount) 103 | } 104 | 105 | @Test 106 | fun testReadLongAtOnce() = testSuspend { 107 | val buffer = ByteArrayBuffer(8) 108 | buffer.writeInt(Int.MAX_VALUE) 109 | buffer.writeInt(Int.MAX_VALUE) 110 | 111 | val source = TestBytesSource(buffer) 112 | val buffered = BufferedBytesSource(source) 113 | 114 | assertEquals(9223372034707292159, buffered.readLong()) 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/commonTest/kotlin/io/ktor/io/ByteArrayBufferTest.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | 6 | class ByteArrayWithDefaultPoolTest : BufferTest() { 7 | override fun createBuffer(): Buffer = ByteArrayBuffer(ByteArrayPool.Default) 8 | } 9 | 10 | class ByteArrayWithEmptyPoolTest : BufferTest() { 11 | override fun createBuffer(): Buffer = ByteArrayBuffer(ByteArrayPool.Empty) 12 | } 13 | 14 | class ByteArrayTest { 15 | @Test 16 | fun testConstructorFromArray() { 17 | val array = ByteArray(10) 18 | val buffer = ByteArrayBuffer(array) 19 | 20 | assertEquals(0, buffer.readIndex) 21 | assertEquals(array.size, buffer.writeIndex) 22 | } 23 | 24 | @Test 25 | fun testConstructorFromPool() { 26 | val buffer = ByteArrayBuffer() 27 | assertEquals(0, buffer.readIndex) 28 | assertEquals(0, buffer.writeIndex) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/commonTest/kotlin/io/ktor/io/TestBytesSource.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | class TestBytesSource(private vararg val buffers: ByteArrayBuffer) : BytesSource() { 4 | internal var readCount = 0 5 | override val closedCause: Throwable? = null 6 | override fun canRead() = readCount < buffers.size 7 | override fun read(): Buffer = buffers[readCount++] 8 | override suspend fun awaitContent() = Unit 9 | override fun cancel(cause: Throwable) = Unit 10 | } 11 | -------------------------------------------------------------------------------- /src/commonTest/kotlin/io/ktor/io/utils/TestBytesDestination.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io.utils 2 | 3 | import io.ktor.io.* 4 | 5 | class TestBytesDestination : BytesDestination() { 6 | internal val buffers = mutableListOf() 7 | internal val writeCount: Int get() = buffers.size 8 | 9 | override var closedCause: Throwable? = null 10 | 11 | override fun canWrite(): Boolean = closedCause != null 12 | 13 | override fun write(buffer: Buffer): Int { 14 | val copy = ByteArrayBuffer(buffer.availableForRead) 15 | val array = ByteArray(buffer.availableForRead) 16 | buffer.copyToByteArray(array) 17 | copy.copyFromByteArray(array) 18 | buffers.add(copy) 19 | buffer.readIndex = buffer.writeIndex 20 | return array.size 21 | } 22 | 23 | override suspend fun flush() = Unit 24 | override suspend fun awaitFreeSpace() = Unit 25 | 26 | override fun close(cause: Throwable?) { 27 | closedCause = cause ?: ClosedDestinationException() 28 | } 29 | 30 | override fun close() { 31 | close(null) 32 | } 33 | 34 | class ClosedDestinationException : IOException("closed") 35 | } 36 | -------------------------------------------------------------------------------- /src/commonTest/kotlin/io/ktor/io/utils/testSuspend.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io.utils 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlin.coroutines.CoroutineContext 5 | import kotlin.coroutines.EmptyCoroutineContext 6 | 7 | expect fun testSuspend( 8 | context: CoroutineContext = EmptyCoroutineContext, 9 | timeoutMillis: Long = 60L * 1000L, 10 | block: suspend CoroutineScope.() -> Unit 11 | ) 12 | -------------------------------------------------------------------------------- /src/jsMain/kotlin/io/ktor/io/CloseableJs.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public actual interface Closeable { 4 | public actual fun close() 5 | } 6 | 7 | @PublishedApi 8 | internal actual fun Throwable.addSuppressedInternal(other: Throwable) { 9 | } 10 | -------------------------------------------------------------------------------- /src/jsMain/kotlin/io/ktor/io/DefaultPool.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public actual abstract class DefaultPool actual constructor( 4 | actual final override val capacity: Int 5 | ) : ObjectPool { 6 | 7 | private val instances = arrayOfNulls(capacity) 8 | private var size = 0 9 | 10 | protected actual abstract fun produceInstance(): T 11 | protected actual open fun disposeInstance(instance: T) {} 12 | 13 | protected actual open fun clearInstance(instance: T): T = instance 14 | protected actual open fun validateInstance(instance: T) {} 15 | 16 | actual final override fun borrow(): T { 17 | if (size == 0) return produceInstance() 18 | val idx = --size 19 | 20 | @Suppress("UNCHECKED_CAST") 21 | val instance = instances[idx] as T 22 | instances[idx] = null 23 | 24 | return clearInstance(instance) 25 | } 26 | 27 | actual final override fun recycle(instance: T) { 28 | validateInstance(instance) 29 | if (size == capacity) { 30 | disposeInstance(instance) 31 | } else { 32 | instances[size++] = instance 33 | } 34 | } 35 | 36 | actual final override fun dispose() { 37 | for (i in 0 until size) { 38 | @Suppress("UNCHECKED_CAST") 39 | val instance = instances[i] as T 40 | instances[i] = null 41 | disposeInstance(instance) 42 | } 43 | size = 0 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/jsMain/kotlin/io/ktor/io/IOExceptionJs.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public actual open class IOException actual constructor(message: String, cause: Throwable?) : 4 | Exception(message, cause) { 5 | public actual constructor(message: String) : this(message, null) 6 | } 7 | 8 | public actual open class EOFException actual constructor(message: String) : IOException(message) 9 | -------------------------------------------------------------------------------- /src/jsTest/kotlin/io/ktor/io/utils/TestUtilsJs.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io.utils 2 | 3 | import kotlinx.coroutines.* 4 | import kotlin.coroutines.CoroutineContext 5 | 6 | @OptIn(DelicateCoroutinesApi::class) 7 | actual fun testSuspend( 8 | context: CoroutineContext, 9 | timeoutMillis: Long, 10 | block: suspend CoroutineScope.() -> Unit 11 | ): dynamic = GlobalScope.promise(block = { 12 | withTimeout(timeoutMillis, block) 13 | }, context = context) 14 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/CloseableJvm.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import java.lang.reflect.Method 4 | 5 | public actual typealias Closeable = java.io.Closeable 6 | 7 | @PublishedApi 8 | internal actual fun Throwable.addSuppressedInternal(other: Throwable) { 9 | AddSuppressedMethod?.invoke(this, other) 10 | } 11 | 12 | private val AddSuppressedMethod: Method? by lazy { 13 | try { 14 | Throwable::class.java.getMethod("addSuppressed", Throwable::class.java) 15 | } catch (t: Throwable) { 16 | null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/DefaultPool.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import kotlinx.atomicfu.atomic 4 | import kotlinx.atomicfu.atomicArrayOfNulls 5 | import kotlinx.atomicfu.locks.SynchronizedObject 6 | import kotlinx.atomicfu.locks.synchronized 7 | 8 | public actual abstract class DefaultPool actual constructor( 9 | actual final override val capacity: Int 10 | ) : ObjectPool { 11 | protected val lock: SynchronizedObject = SynchronizedObject() 12 | 13 | private val instances = atomicArrayOfNulls(capacity) 14 | private var size by atomic(0) 15 | 16 | protected actual abstract fun produceInstance(): T 17 | protected actual open fun disposeInstance(instance: T) {} 18 | 19 | protected actual open fun clearInstance(instance: T): T = instance 20 | protected actual open fun validateInstance(instance: T) {} 21 | 22 | public actual final override fun borrow(): T = synchronized(lock) { 23 | if (size == 0) return produceInstance() 24 | val idx = --size 25 | 26 | @Suppress("UNCHECKED_CAST") 27 | val instance = instances[idx].value as T 28 | instances[idx].value = null 29 | 30 | return clearInstance(instance) 31 | } 32 | 33 | public actual final override fun recycle(instance: T) { 34 | synchronized(lock) { 35 | validateInstance(instance) 36 | if (size == capacity) { 37 | disposeInstance(instance) 38 | } else { 39 | instances[size++].value = instance 40 | } 41 | } 42 | } 43 | 44 | public actual final override fun dispose() { 45 | synchronized(lock) { 46 | for (i in 0 until size) { 47 | @Suppress("UNCHECKED_CAST") 48 | val instance = instances[i].value as T 49 | instances[i].value = null 50 | disposeInstance(instance) 51 | } 52 | size = 0 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/DirectByteBufferPool.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import java.nio.ByteBuffer 4 | import java.nio.ByteOrder 5 | 6 | public class ByteBufferPool( 7 | capacity: Int = DEFAULT_POOL_CAPACITY, 8 | public val direct: Boolean = true, 9 | public val bufferSize: Int = DEFAULT_BUFFER_SIZE 10 | ) : DefaultPool(capacity) { 11 | 12 | override fun produceInstance(): ByteBuffer = if (direct) { 13 | ByteBuffer.allocateDirect(bufferSize)!! 14 | } else { 15 | ByteBuffer.allocate(bufferSize)!! 16 | } 17 | 18 | override fun clearInstance(instance: ByteBuffer): ByteBuffer = instance.apply { 19 | clear() 20 | order(ByteOrder.BIG_ENDIAN) 21 | } 22 | 23 | override fun validateInstance(instance: ByteBuffer) { 24 | check(instance.capacity() == bufferSize) 25 | check(instance.isDirect) 26 | } 27 | 28 | public companion object { 29 | public val Default: ObjectPool get() = Direct 30 | 31 | public val Direct: ObjectPool = ByteBufferPool(direct = true) 32 | 33 | public val Heap: ObjectPool = ByteBufferPool(direct = false) 34 | 35 | public val Empty: ObjectPool = ByteBufferPool(capacity = 0) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/FileBytesDestination.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import java.lang.Integer.min 4 | import java.nio.channels.ClosedChannelException 5 | import java.nio.channels.FileChannel 6 | import java.nio.file.OpenOption 7 | import java.nio.file.Path 8 | import java.nio.file.StandardOpenOption 9 | import java.nio.file.attribute.FileAttribute 10 | 11 | public fun FileBytesDestination( 12 | file: Path, 13 | options: Set = setOf(StandardOpenOption.CREATE, StandardOpenOption.WRITE), 14 | vararg attrs: FileAttribute 15 | ): FileBytesDestination = FileBytesDestination(FileChannel.open(file, options, *attrs)) 16 | 17 | public class FileBytesDestination(private val channel: FileChannel) : BytesDestination() { 18 | 19 | @Volatile 20 | override var closedCause: Throwable? = null 21 | private set 22 | 23 | override fun canWrite(): Boolean { 24 | if (closedCause is ClosedChannelException) return false 25 | closedCause?.let { throw it } 26 | return true 27 | } 28 | 29 | override fun write(buffer: Buffer): Int { 30 | closedCause?.let { throw it } 31 | 32 | try { 33 | if (buffer is JvmBuffer) { 34 | return channel.write(buffer.buffer) 35 | } 36 | return slowWrite(buffer) 37 | } catch (cause: Throwable) { 38 | close(cause) 39 | throw cause 40 | } 41 | } 42 | 43 | private fun slowWrite(buffer: Buffer): Int { 44 | ByteBufferPool.Default.useInstance { byteBuffer -> 45 | val toWrite = min(buffer.availableForRead, byteBuffer.remaining()) 46 | if (buffer is ByteArrayBuffer) { 47 | byteBuffer.put(buffer.array, buffer.readIndex, toWrite) 48 | buffer.readIndex += toWrite 49 | } else { 50 | repeat(toWrite) { 51 | byteBuffer.put(buffer.readByte()) 52 | } 53 | } 54 | byteBuffer.flip() 55 | return channel.write(byteBuffer) 56 | } 57 | } 58 | 59 | public override suspend fun awaitFreeSpace() { 60 | closedCause?.let { throw it } 61 | } 62 | 63 | override suspend fun flush() { 64 | closedCause?.let { throw it } 65 | } 66 | 67 | override fun close(cause: Throwable?) { 68 | closedCause = cause ?: ClosedChannelException() 69 | channel.close() 70 | } 71 | 72 | override fun close() { 73 | close(null) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/FileBytesSource.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import java.nio.ByteBuffer 4 | import java.nio.channels.AsynchronousCloseException 5 | import java.nio.channels.AsynchronousFileChannel 6 | import java.nio.channels.CompletionHandler 7 | import java.nio.file.OpenOption 8 | import java.nio.file.Path 9 | import java.nio.file.StandardOpenOption 10 | import java.util.concurrent.ExecutorService 11 | import kotlin.coroutines.Continuation 12 | import kotlin.coroutines.resume 13 | import kotlin.coroutines.resumeWithException 14 | import kotlin.coroutines.suspendCoroutine 15 | 16 | public fun FileBytesSource( 17 | file: Path, 18 | options: Set = setOf(StandardOpenOption.READ), 19 | executor: ExecutorService? = null 20 | ): FileBytesSource = FileBytesSource(AsynchronousFileChannel.open(file, options, executor)) 21 | 22 | public class FileBytesSource(private val channel: AsynchronousFileChannel) : BytesSource() { 23 | 24 | @Volatile 25 | private var bytesRead = 0L 26 | 27 | @Volatile 28 | private var isClosedForRead = false 29 | 30 | @Volatile 31 | override var closedCause: Throwable? = null 32 | private set 33 | 34 | private var state: JvmBuffer? = null 35 | 36 | override fun canRead(): Boolean { 37 | closedCause?.let { throw it } 38 | 39 | return !isClosedForRead 40 | } 41 | 42 | override fun read(): Buffer { 43 | closedCause?.let { throw it } 44 | 45 | return state.also { state = null } ?: Buffer.Empty 46 | } 47 | 48 | override suspend fun awaitContent() { 49 | closedCause?.let { throw it } 50 | 51 | val buffer = ByteBufferPool.Direct.borrow() 52 | val count = channel.read(buffer) 53 | if (count == -1) { 54 | isClosedForRead = true 55 | ByteBufferPool.Direct.recycle(buffer) 56 | return 57 | } 58 | 59 | bytesRead += count 60 | state = JvmBuffer(buffer.flip(), ByteBufferPool.Direct) 61 | } 62 | 63 | override fun cancel(cause: Throwable) { 64 | if (closedCause != null) return 65 | closedCause = cause 66 | channel.close() 67 | } 68 | 69 | private lateinit var readCompletionContinuation: Continuation 70 | 71 | private val readCompletionHandler = object : CompletionHandler { 72 | override fun completed(result: Int, attachment: Unit) { 73 | readCompletionContinuation.resume(result) 74 | } 75 | 76 | override fun failed(cause: Throwable, attachment: Unit) { 77 | if (cause is AsynchronousCloseException) { 78 | check(closedCause != null) 79 | readCompletionContinuation.resumeWithException(closedCause!!) 80 | return 81 | } 82 | 83 | cancel(cause) 84 | readCompletionContinuation.resumeWithException(cause) 85 | } 86 | } 87 | 88 | private suspend fun AsynchronousFileChannel.read( 89 | byteBuffer: ByteBuffer 90 | ): Int = suspendCoroutine { continuation -> 91 | readCompletionContinuation = continuation 92 | read(byteBuffer, bytesRead, Unit, readCompletionHandler) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/IOExceptionJvm.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public actual typealias IOException = java.io.IOException 4 | 5 | public actual typealias EOFException = java.io.EOFException 6 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/JvmBuffer.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import java.lang.Integer.min 4 | import java.nio.ByteBuffer 5 | 6 | /** 7 | * The [Buffer] implementation using [ByteBuffer] class on the JVM. 8 | * 9 | * @constructor creates buffer prepared for reading. 10 | */ 11 | public class JvmBuffer( 12 | buffer: ByteBuffer, 13 | private val pool: ObjectPool = ByteBufferPool.Default 14 | ) : Buffer { 15 | 16 | /** 17 | * Creates a new [JvmBuffer] instance with the [ByteBuffer] instance from the [pool]. 18 | * 19 | * The buffer is empty and prepared for write operations. 20 | */ 21 | public constructor(capacity: Int) : this( 22 | ByteBuffer.allocateDirect(capacity).limit(0), 23 | ByteBufferPool.Empty 24 | ) 25 | 26 | /** 27 | * Creates a new [JvmBuffer] instance with the [ByteBuffer] instance from the [pool]. 28 | * 29 | * The buffer is empty and prepared for write operations. 30 | */ 31 | public constructor(pool: ObjectPool = ByteBufferPool.Default) : this(pool.borrow().limit(0), pool) 32 | 33 | /** 34 | * Provides access to the underlying [ByteBuffer]. 35 | * 36 | * The [buffer.position()] reflects [readIndex] and [buffer.limit()] reflects [writeIndex]. 37 | * 38 | * All modifications of the [ByteBuffer] is reflected by the [JvmBuffer] itself. 39 | */ 40 | @Suppress("CanBePrimaryConstructorProperty") 41 | public var buffer: ByteBuffer = buffer 42 | private set 43 | 44 | override var readIndex: Int 45 | get() = buffer.position() 46 | set(value) { 47 | buffer.position(value) 48 | } 49 | 50 | override var writeIndex: Int 51 | get() = buffer.limit() 52 | set(value) { 53 | buffer.limit(value) 54 | } 55 | 56 | override val capacity: Int 57 | get() = buffer.capacity() 58 | 59 | override fun copyToByteArrayAt(index: Int, destination: ByteArray, startIndex: Int, endIndex: Int): Int { 60 | require(startIndex >= 0) { "startIndex should be non-negative: $startIndex" } 61 | require(startIndex <= endIndex) { "startIndex should be less than or equal to endIndex: $startIndex, $endIndex" } 62 | require(endIndex <= destination.size) { "endIndex should be less than or equal to destination.size: $endIndex, ${destination.size}" } 63 | require(index < capacity) { "index should be less than capacity: $index, $capacity" } 64 | 65 | val count = min(endIndex - startIndex, capacity - index) 66 | randomAccess { 67 | it.position(index) 68 | buffer.get(destination, startIndex, count) 69 | } 70 | 71 | return count 72 | } 73 | 74 | override fun copyToByteArray(destination: ByteArray, startIndex: Int, endIndex: Int): Int { 75 | require(startIndex >= 0) { "startIndex should be non-negative: $startIndex" } 76 | require(startIndex <= endIndex) { "startIndex should be less than or equal to endIndex: $startIndex, $endIndex" } 77 | require(endIndex <= destination.size) { "endIndex should be less than or equal to destination.size: $endIndex, ${destination.size}" } 78 | 79 | val count = min(endIndex - startIndex, buffer.remaining()) 80 | buffer.get(destination, startIndex, count) 81 | return count 82 | } 83 | 84 | /** 85 | * Return the underlying buffer to the pool. 86 | */ 87 | override fun close() { 88 | pool.recycle(buffer) 89 | } 90 | 91 | override fun compact() { 92 | buffer.compact() 93 | } 94 | 95 | override fun getByteAt(index: Int): Byte = buffer.get(index) 96 | 97 | override fun getShortAt(index: Int): Short = buffer.getShort(index) 98 | 99 | override fun getIntAt(index: Int): Int = buffer.getInt(index) 100 | 101 | override fun getLongAt(index: Int): Long = buffer.getLong(index) 102 | 103 | override fun setByteAt(index: Int, value: Byte) { 104 | randomAccess { 105 | it.put(index, value) 106 | } 107 | } 108 | 109 | override fun setShortAt(index: Int, value: Short) { 110 | randomAccess { 111 | it.putShort(index, value) 112 | } 113 | } 114 | 115 | override fun setIntAt(index: Int, value: Int) { 116 | randomAccess { 117 | it.putInt(index, value) 118 | } 119 | } 120 | 121 | override fun setLongAt(index: Int, value: Long) { 122 | randomAccess { 123 | it.putLong(index, value) 124 | } 125 | } 126 | 127 | override fun copyFromBufferAt(index: Int, value: Buffer): Int { 128 | var current = index 129 | while (value.isNotEmpty) { 130 | setByteAt(current++, value.readByte()) 131 | } 132 | 133 | return current - index 134 | } 135 | 136 | override fun copyFromByteArrayAt(index: Int, value: ByteArray, startIndex: Int, endIndex: Int): Int { 137 | check(index < capacity) { "Index should be less than capacity: $index, $capacity" } 138 | check(startIndex >= 0) { "startPosition should be non-negative: $startIndex" } 139 | check(startIndex <= endIndex) { "startPosition should be less than or equal to endPosition: $startIndex, $endIndex" } 140 | check(endIndex <= value.size) { "endPosition should be less than or equal to value.size: $endIndex, ${value.size}" } 141 | 142 | 143 | val count = min(endIndex - startIndex, capacity - index) 144 | 145 | randomAccess { 146 | it.position(index) 147 | buffer.put(value, startIndex, count) 148 | } 149 | 150 | return count 151 | } 152 | 153 | private fun randomAccess(block: (ByteBuffer) -> Unit) { 154 | val oldPosition = buffer.position() 155 | val oldLimit = buffer.limit() 156 | try { 157 | buffer.position(0) 158 | buffer.limit(capacity) 159 | block(buffer) 160 | } finally { 161 | buffer.position(oldPosition) 162 | buffer.limit(oldLimit) 163 | } 164 | } 165 | } 166 | 167 | -------------------------------------------------------------------------------- /src/jvmMain/kotlin/io/ktor/io/JvmBufferPool.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import java.nio.ByteBuffer 4 | 5 | public class JvmBufferPool( 6 | capacity: Int = DEFAULT_POOL_CAPACITY, 7 | public val byteBufferPool: ObjectPool = ByteBufferPool.Default 8 | ) : DefaultPool(capacity) { 9 | 10 | override fun produceInstance(): JvmBuffer = JvmBuffer(byteBufferPool) 11 | 12 | public companion object { 13 | public val Default: ObjectPool = JvmBufferPool() 14 | 15 | public val Empty: ObjectPool = JvmBufferPool( 16 | capacity = 0, 17 | byteBufferPool = ByteBufferPool.Empty 18 | ) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/jvmTest/kotlin/io/ktor/io/FilesTest.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import kotlinx.coroutines.runBlocking 4 | import java.nio.file.Files 5 | import kotlin.io.path.deleteIfExists 6 | import kotlin.io.path.readText 7 | import kotlin.io.path.writeText 8 | import kotlin.test.Test 9 | import kotlin.test.assertEquals 10 | 11 | class FilesTest { 12 | 13 | @Test 14 | fun testCopyingFile(): Unit = runBlocking { 15 | val content = buildString { repeat(100000) { append("testString$it") } } 16 | 17 | val originalFile = Files.createTempFile("test", "origin") 18 | originalFile.writeText(content) 19 | val fileCopy = Files.createTempFile("test", "copy") 20 | 21 | val source = FileBytesSource(originalFile) 22 | val destination = FileBytesDestination(fileCopy) 23 | 24 | while (source.canRead()) { 25 | val buffer = source.read() 26 | destination.write(buffer) 27 | destination.awaitFreeSpace() 28 | source.awaitContent() 29 | } 30 | destination.flush() 31 | source.cancel() 32 | destination.close() 33 | 34 | val copiedContent = fileCopy.readText() 35 | 36 | originalFile.deleteIfExists() 37 | fileCopy.deleteIfExists() 38 | 39 | assertEquals(content, copiedContent) 40 | } 41 | 42 | @Test 43 | fun testCopyingFileBuffered(): Unit = runBlocking { 44 | val content = buildString { repeat(100000) { append("testString$it") } } 45 | 46 | val originalFile = Files.createTempFile("tmp", "original") 47 | originalFile.writeText(content) 48 | val fileCopy = Files.createTempFile("tmp", "copy") 49 | 50 | val source = BufferedBytesSource(FileBytesSource(originalFile)) 51 | val destination = BufferedBytesDestination(FileBytesDestination(fileCopy), 12 * 1024) 52 | 53 | var writeCount = 0 54 | while (source.canRead()) { 55 | val buffer = source.read() 56 | val count = destination.write(buffer) 57 | writeCount += count 58 | 59 | println("Written $buffer $count/$writeCount/${content.length} bytes") 60 | 61 | destination.awaitFreeSpace() 62 | source.awaitContent() 63 | } 64 | 65 | destination.flush() 66 | source.cancel() 67 | destination.close() 68 | 69 | val copiedContent = fileCopy.readText() 70 | 71 | originalFile.deleteIfExists() 72 | fileCopy.deleteIfExists() 73 | 74 | assertEquals(content, copiedContent) 75 | } 76 | } -------------------------------------------------------------------------------- /src/jvmTest/kotlin/io/ktor/io/JvmBufferTest.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import org.junit.jupiter.api.Test 4 | import java.nio.ByteBuffer 5 | import kotlin.test.assertEquals 6 | 7 | class JvmBufferWithDefaultPoolTest : BufferTest() { 8 | override fun createBuffer(): Buffer = JvmBuffer(ByteBufferPool.Default) 9 | } 10 | 11 | class JvmBufferWithEmptyPoolTest : BufferTest() { 12 | override fun createBuffer(): Buffer = JvmBuffer(ByteBufferPool.Empty) 13 | } 14 | 15 | class JvmBufferTest { 16 | 17 | @Test 18 | fun testConstructorFromByteBuffer() { 19 | val data = ByteBuffer.allocateDirect(1024) 20 | data.position(21) 21 | data.limit(42) 22 | 23 | val buffer = JvmBuffer(data) 24 | assertEquals(21, buffer.readIndex) 25 | assertEquals(42, buffer.writeIndex) 26 | } 27 | 28 | @Test 29 | fun testConstructorFromPool() { 30 | val buffer = JvmBuffer(ByteBufferPool.Default) 31 | assertEquals(0, buffer.readIndex) 32 | assertEquals(0, buffer.writeIndex) 33 | } 34 | } -------------------------------------------------------------------------------- /src/jvmTest/kotlin/io/ktor/io/utils/TestUtilsJvm.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io.utils 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlinx.coroutines.runBlocking 5 | import kotlinx.coroutines.withTimeout 6 | import kotlin.coroutines.CoroutineContext 7 | 8 | actual fun testSuspend( 9 | context: CoroutineContext, 10 | timeoutMillis: Long, 11 | block: suspend CoroutineScope.() -> Unit 12 | ): Unit = runBlocking(context) { 13 | withTimeout(timeoutMillis, block) 14 | } 15 | -------------------------------------------------------------------------------- /src/nativeMain/kotlin/io/ktor/io/Closeable.native.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public actual interface Closeable { 4 | public actual fun close() 5 | } 6 | 7 | @PublishedApi 8 | internal actual fun Throwable.addSuppressedInternal(other: Throwable) { 9 | } 10 | -------------------------------------------------------------------------------- /src/nativeMain/kotlin/io/ktor/io/DefaultPool.native.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | import kotlinx.atomicfu.atomic 4 | import kotlinx.atomicfu.atomicArrayOfNulls 5 | import kotlinx.atomicfu.locks.SynchronizedObject 6 | import kotlinx.atomicfu.locks.synchronized 7 | 8 | public actual abstract class DefaultPool actual constructor( 9 | actual final override val capacity: Int 10 | ) : ObjectPool { 11 | private val lock: SynchronizedObject = SynchronizedObject() 12 | 13 | private val instances = atomicArrayOfNulls(capacity) 14 | private var size by atomic(0) 15 | 16 | protected actual abstract fun produceInstance(): T 17 | protected actual open fun disposeInstance(instance: T) {} 18 | 19 | protected actual open fun clearInstance(instance: T): T = instance 20 | protected actual open fun validateInstance(instance: T) {} 21 | 22 | public actual final override fun borrow(): T = synchronized(lock) { 23 | if (size == 0) return produceInstance() 24 | val idx = --size 25 | 26 | @Suppress("UNCHECKED_CAST") 27 | val instance = instances[idx].value as T 28 | instances[idx].value = null 29 | 30 | return clearInstance(instance) 31 | } 32 | 33 | public actual final override fun recycle(instance: T) { 34 | synchronized(lock) { 35 | validateInstance(instance) 36 | if (size == capacity) { 37 | disposeInstance(instance) 38 | } else { 39 | instances[size++].value = instance 40 | } 41 | } 42 | } 43 | 44 | public actual final override fun dispose() { 45 | synchronized(lock) { 46 | for (i in 0 until size) { 47 | @Suppress("UNCHECKED_CAST") 48 | val instance = instances[i].value as T 49 | instances[i].value = null 50 | disposeInstance(instance) 51 | } 52 | size = 0 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/nativeMain/kotlin/io/ktor/io/IOException.native.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io 2 | 3 | public actual open class IOException 4 | actual constructor(message: String, cause: Throwable?) : Exception(message, cause) { 5 | public actual constructor(message: String) : this(message, null) 6 | } 7 | 8 | public actual open class EOFException actual constructor(message: String) : IOException(message) 9 | -------------------------------------------------------------------------------- /src/nativeTest/kotlin/io/ktor/io/utils/TestUtilsNative.kt: -------------------------------------------------------------------------------- 1 | package io.ktor.io.utils 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlinx.coroutines.runBlocking 5 | import platform.posix.usleep 6 | import kotlin.coroutines.CoroutineContext 7 | import kotlin.native.concurrent.FutureState 8 | import kotlin.native.concurrent.TransferMode 9 | import kotlin.native.concurrent.Worker 10 | import kotlin.system.getTimeMillis 11 | import kotlin.time.Duration.Companion.milliseconds 12 | 13 | actual fun testSuspend( 14 | context: CoroutineContext, 15 | timeoutMillis: Long, 16 | block: suspend CoroutineScope.() -> Unit 17 | ) { 18 | executeInWorker(timeoutMillis) { 19 | runBlocking { 20 | block() 21 | } 22 | } 23 | } 24 | 25 | private var TEST_WORKER: Worker = createTestWorker() 26 | private val SLEEP_TIME: UInt = 10.milliseconds.inWholeMicroseconds.toUInt() 27 | 28 | internal fun executeInWorker(timeout: Long, block: () -> Unit) { 29 | val result = TEST_WORKER.execute(TransferMode.UNSAFE, { block }) { 30 | it() 31 | } 32 | 33 | val endTime = getTimeMillis() + timeout 34 | while (result.state == FutureState.SCHEDULED && endTime > getTimeMillis()) { 35 | usleep(SLEEP_TIME) 36 | } 37 | 38 | when (result.state) { 39 | FutureState.SCHEDULED -> { 40 | TEST_WORKER.requestTermination(processScheduledJobs = false) 41 | TEST_WORKER = createTestWorker() 42 | error("Test is timed out") 43 | } 44 | else -> { 45 | result.consume { } 46 | } 47 | } 48 | } 49 | 50 | private fun createTestWorker(): Worker = Worker.start( 51 | name = "Ktor Test Worker", 52 | errorReporting = true 53 | ) 54 | --------------------------------------------------------------------------------