diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..b2d6788
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,75 @@
+name: CI
+
+on:
+ push:
+ branches:
+ - master
+ - github-workflow
+jobs:
+ Build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout latest
+ uses: actions/checkout@v2
+
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: 8.*
+
+ - name: Install dependencies
+ run: dotnet restore
+
+ - name: Build
+ run: dotnet build --configuration Release --no-restore
+
+ - name: Upload Artificats
+ uses: actions/upload-artifact@v4
+ with:
+ name: TestBinaries
+ path: HttpTwo.Tests/**/bin/*
+
+ UnitTest:
+ name: Run Unit Tests
+ needs: Build
+ runs-on: windows-latest
+ steps:
+ - name: Checkout latest
+ uses: actions/checkout@v2
+
+ - name: Use Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20.x"
+
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: 6.*
+
+ - uses: actions/download-artifact@v4
+ with:
+ name: TestBinaries
+ path: HttpTwo.Tests
+
+ - name: Install dependencies
+ working-directory: ./HttpTwo.Tests/node-http2
+ run: npm install
+
+ - name: Unit Test (.NET 6.0)
+ if: ${{ !cancelled() }}
+ run: dotnet test --verbosity normal --logger "trx;LogFileName=net6.trx" --results-directory coverage bin/Release/net6.0/HttpTwo.Tests.dll
+ working-directory: ./HttpTwo.Tests
+
+ - name: Unit Test (.NET Framework 4.6.2)
+ if: ${{ !cancelled() }}
+ run: dotnet test --verbosity normal --logger "trx;LogFileName=net462.trx" --results-directory coverage bin/Release/net462/HttpTwo.Tests.dll
+ working-directory: ./HttpTwo.Tests
+
+ - uses: dorny/test-reporter@v1
+ if: success() || failure() # run this step even if previous step failed
+ with:
+ name: Test Result
+ path: HttpTwo.Tests/coverage/*.trx
+ reporter: dotnet-trx
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..7270bb9
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,31 @@
+name: Release to NuGet
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ timeout-minutes: 5
+ steps:
+ - name: Checkout latest
+ uses: actions/checkout@v2
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: 8.*
+
+ - name: Version Output
+ run: echo ${{ github.event.release.tag_name }} # Output: 1.1.2
+
+ - name: Build
+ run: dotnet build --configuration Release
+
+ - name: Generate package
+ run: dotnet pack --no-build -c Release -o out /p:Version=${{ github.event.release.tag_name }}
+
+ - name: Publish
+ run: dotnet nuget push ./out/*.nupkg --api-key ${{secrets.NUGET_API_KEY}} --source https://api.nuget.org/v3/index.json --skip-duplicate
+
\ No newline at end of file
diff --git a/HttpTwo.HPack/Decoder.cs b/HttpTwo.HPack/Decoder.cs
deleted file mode 100644
index 1695491..0000000
--- a/HttpTwo.HPack/Decoder.cs
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.IO;
-
-namespace HttpTwo.HPack
-{
- public class Decoder
- {
- private static IOException DECOMPRESSION_EXCEPTION = new IOException("decompression failure");
-
- private static byte[] EMPTY = { };
-
- private DynamicTable dynamicTable;
-
- private int maxHeaderSize;
- private int maxDynamicTableSize;
- private int encoderMaxDynamicTableSize;
- private bool maxDynamicTableSizeChangeRequired;
-
- private long headerSize;
- private State state;
- private HPackUtil.IndexType indexType;
- private int index;
- private bool huffmanEncoded;
- private int skipLength;
- private int nameLength;
- private int valueLength;
- private byte[] name;
-
- public enum State
- {
- READ_HEADER_REPRESENTATION,
- READ_MAX_DYNAMIC_TABLE_SIZE,
- READ_INDEXED_HEADER,
- READ_INDEXED_HEADER_NAME,
- READ_LITERAL_HEADER_NAME_LENGTH_PREFIX,
- READ_LITERAL_HEADER_NAME_LENGTH,
- READ_LITERAL_HEADER_NAME,
- SKIP_LITERAL_HEADER_NAME,
- READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX,
- READ_LITERAL_HEADER_VALUE_LENGTH,
- READ_LITERAL_HEADER_VALUE,
- SKIP_LITERAL_HEADER_VALUE
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Max header size.
- /// Max header table size.
- public Decoder(int maxHeaderSize, int maxHeaderTableSize)
- {
- this.dynamicTable = new DynamicTable(maxHeaderTableSize);
- this.maxHeaderSize = maxHeaderSize;
- this.maxDynamicTableSize = maxHeaderTableSize;
- this.encoderMaxDynamicTableSize = maxHeaderTableSize;
- this.maxDynamicTableSizeChangeRequired = false;
- this.Reset();
- }
-
- private void Reset()
- {
- this.headerSize = 0;
- this.state = State.READ_HEADER_REPRESENTATION;
- this.indexType = HPackUtil.IndexType.NONE;
- }
-
- ///
- /// Decode the header block into header fields.
- ///
- /// Input.
- /// Header listener.
- public void Decode(BinaryReader input, AddHeaderDelegate addHeaderDelegate)
- {
- while(input.BaseStream.Length - input.BaseStream.Position > 0) {
- switch(this.state) {
- case State.READ_HEADER_REPRESENTATION:
- sbyte b = input.ReadSByte();
- if (maxDynamicTableSizeChangeRequired && (b & 0xE0) != 0x20) {
- // Encoder MUST signal maximum dynamic table size change
- throw new IOException("max dynamic table size change required");
- }
- if (b < 0) {
- // Indexed Header Field
- index = b & 0x7F;
- if (index == 0) {
- throw new IOException("illegal index value (" + index + ")");
- } else if (index == 0x7F) {
- state = State.READ_INDEXED_HEADER;
- } else {
- this.IndexHeader(index, addHeaderDelegate);
- }
- } else if ((b & 0x40) == 0x40) {
- // Literal Header Field with Incremental Indexing
- indexType = HPackUtil.IndexType.INCREMENTAL;
- index = b & 0x3F;
- if (index == 0) {
- state = State.READ_LITERAL_HEADER_NAME_LENGTH_PREFIX;
- } else if (index == 0x3F) {
- state = State.READ_INDEXED_HEADER_NAME;
- } else {
- // Index was stored as the prefix
- this.ReadName(index);
- state = State.READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
- }
- } else if ((b & 0x20) == 0x20) {
- // Dynamic Table Size Update
- index = b & 0x1F;
- if (index == 0x1F) {
- state = State.READ_MAX_DYNAMIC_TABLE_SIZE;
- } else {
- this.SetDynamicTableSize(index);
- state = State.READ_HEADER_REPRESENTATION;
- }
- } else {
- // Literal Header Field without Indexing / never Indexed
- indexType = ((b & 0x10) == 0x10) ? HPackUtil.IndexType.NEVER : HPackUtil.IndexType.NONE;
- index = b & 0x0F;
- if (index == 0) {
- state = State.READ_LITERAL_HEADER_NAME_LENGTH_PREFIX;
- } else if (index == 0x0F) {
- state = State.READ_INDEXED_HEADER_NAME;
- } else {
- // Index was stored as the prefix
- this.ReadName(index);
- state = State.READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
- }
- }
- break;
-
- case State.READ_MAX_DYNAMIC_TABLE_SIZE:
- int maxSize = Decoder.DecodeULE128(input);
- if (maxSize == -1) {
- return;
- }
-
- // Check for numerical overflow
- if (maxSize > int.MaxValue - index) {
- throw DECOMPRESSION_EXCEPTION;
- }
-
- this.SetDynamicTableSize(index + maxSize);
- state = State.READ_HEADER_REPRESENTATION;
- break;
-
- case State.READ_INDEXED_HEADER:
- int headerIndex = Decoder.DecodeULE128(input);
- if (headerIndex == -1) {
- return;
- }
-
- // Check for numerical overflow
- if (headerIndex > int.MaxValue - index) {
- throw DECOMPRESSION_EXCEPTION;
- }
-
- this.IndexHeader(index + headerIndex, addHeaderDelegate);
- state = State.READ_HEADER_REPRESENTATION;
- break;
-
- case State.READ_INDEXED_HEADER_NAME:
- // Header Name matches an entry in the Header Table
- int nameIndex = Decoder.DecodeULE128(input);
- if (nameIndex == -1) {
- return;
- }
-
- // Check for numerical overflow
- if (nameIndex > int.MaxValue - index) {
- throw DECOMPRESSION_EXCEPTION;
- }
-
- this.ReadName(index + nameIndex);
- state = State.READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
- break;
-
- case State.READ_LITERAL_HEADER_NAME_LENGTH_PREFIX:
- b = input.ReadSByte();
- huffmanEncoded = (b & 0x80) == 0x80;
- index = b & 0x7F;
- if (index == 0x7f) {
- state = State.READ_LITERAL_HEADER_NAME_LENGTH;
- } else {
- nameLength = index;
-
- // Disallow empty names -- they cannot be represented in HTTP/1.x
- if (nameLength == 0) {
- throw DECOMPRESSION_EXCEPTION;
- }
-
- // Check name length against max header size
- if (this.ExceedsMaxHeaderSize(nameLength)) {
- if (indexType == HPackUtil.IndexType.NONE) {
- // Name is unused so skip bytes
- name = EMPTY;
- this.skipLength = nameLength;
- state = State.SKIP_LITERAL_HEADER_NAME;
- break;
- }
-
- // Check name length against max dynamic table size
- if (nameLength + HeaderField.HEADER_ENTRY_OVERHEAD > this.dynamicTable.Capacity) {
- this.dynamicTable.Clear();
- name = EMPTY;
- this.skipLength = nameLength;
- state = State.SKIP_LITERAL_HEADER_NAME;
- break;
- }
- }
- state = State.READ_LITERAL_HEADER_NAME;
- }
- break;
-
- case State.READ_LITERAL_HEADER_NAME_LENGTH:
- // Header Name is a Literal String
- nameLength = Decoder.DecodeULE128(input);
- if (nameLength == -1) {
- return;
- }
-
- // Check for numerical overflow
- if (nameLength > int.MaxValue - index) {
- throw DECOMPRESSION_EXCEPTION;
- }
- nameLength += index;
-
- // Check name length against max header size
- if (this.ExceedsMaxHeaderSize(nameLength)) {
- if (indexType == HPackUtil.IndexType.NONE) {
- // Name is unused so skip bytes
- name = EMPTY;
- this.skipLength = nameLength;
- state = State.SKIP_LITERAL_HEADER_NAME;
- break;
- }
-
- // Check name length against max dynamic table size
- if (nameLength + HeaderField.HEADER_ENTRY_OVERHEAD > this.dynamicTable.Capacity) {
- this.dynamicTable.Clear();
- name = EMPTY;
- this.skipLength = nameLength;
- state = State.SKIP_LITERAL_HEADER_NAME;
- break;
- }
- }
- state = State.READ_LITERAL_HEADER_NAME;
- break;
-
- case State.READ_LITERAL_HEADER_NAME:
- // Wait until entire name is readable
- if (input.BaseStream.Length - input.BaseStream.Position < nameLength) {
- return;
- }
-
- name = this.ReadStringLiteral(input, nameLength);
- state = State.READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
- break;
-
- case State.SKIP_LITERAL_HEADER_NAME:
-
- this.skipLength -= (int)input.BaseStream.Seek(this.skipLength, SeekOrigin.Current);
- if (this.skipLength < 0) {
- this.skipLength = 0;
- }
- if (this.skipLength == 0) {
- state = State.READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
- }
- break;
-
- case State.READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX:
- b = input.ReadSByte();
- huffmanEncoded = (b & 0x80) == 0x80;
- index = b & 0x7F;
- if (index == 0x7f) {
- state = State.READ_LITERAL_HEADER_VALUE_LENGTH;
- } else {
- this.valueLength = index;
-
- // Check new header size against max header size
- long newHeaderSize1 = (long)nameLength + (long)this.valueLength;
- if (this.ExceedsMaxHeaderSize(newHeaderSize1)) {
- // truncation will be reported during endHeaderBlock
- headerSize = maxHeaderSize + 1;
-
- if (indexType == HPackUtil.IndexType.NONE) {
- // Value is unused so skip bytes
- state = State.SKIP_LITERAL_HEADER_VALUE;
- break;
- }
-
- // Check new header size against max dynamic table size
- if (newHeaderSize1 + HeaderField.HEADER_ENTRY_OVERHEAD > this.dynamicTable.Capacity) {
- this.dynamicTable.Clear();
- state = State.SKIP_LITERAL_HEADER_VALUE;
- break;
- }
- }
-
- if (this.valueLength == 0) {
- this.InsertHeader(addHeaderDelegate, name, EMPTY, indexType);
- state = State.READ_HEADER_REPRESENTATION;
- } else {
- state = State.READ_LITERAL_HEADER_VALUE;
- }
- }
- break;
-
- case State.READ_LITERAL_HEADER_VALUE_LENGTH:
- // Header Value is a Literal String
- this.valueLength = Decoder.DecodeULE128(input);
- if (this.valueLength == -1) {
- return;
- }
-
- // Check for numerical overflow
- if (this.valueLength > int.MaxValue - index) {
- throw DECOMPRESSION_EXCEPTION;
- }
- this.valueLength += index;
-
- // Check new header size against max header size
- long newHeaderSize2 = (long)nameLength + (long)this.valueLength;
- if (newHeaderSize2 + headerSize > maxHeaderSize) {
- // truncation will be reported during endHeaderBlock
- headerSize = maxHeaderSize + 1;
-
- if (indexType == HPackUtil.IndexType.NONE) {
- // Value is unused so skip bytes
- state = State.SKIP_LITERAL_HEADER_VALUE;
- break;
- }
-
- // Check new header size against max dynamic table size
- if (newHeaderSize2 + HeaderField.HEADER_ENTRY_OVERHEAD > this.dynamicTable.Capacity) {
- this.dynamicTable.Clear();
- state = State.SKIP_LITERAL_HEADER_VALUE;
- break;
- }
- }
- state = State.READ_LITERAL_HEADER_VALUE;
- break;
-
- case State.READ_LITERAL_HEADER_VALUE:
- // Wait until entire value is readable
- if (input.BaseStream.Length - input.BaseStream.Position < this.valueLength) {
- return;
- }
-
- byte[] value = this.ReadStringLiteral(input, this.valueLength);
- this.InsertHeader(addHeaderDelegate, name, value, indexType);
- state = State.READ_HEADER_REPRESENTATION;
- break;
-
- case State.SKIP_LITERAL_HEADER_VALUE:
- this.valueLength -= (int)input.BaseStream.Seek(this.valueLength, SeekOrigin.Current);
- if (this.valueLength < 0) {
- this.valueLength = 0;
- }
- if (this.valueLength == 0) {
- state = State.READ_HEADER_REPRESENTATION;
- }
- break;
-
- default:
- throw new Exception("should not reach here");
- }
- }
- }
-
- ///
- /// End the current header block. Returns if the header field has been truncated.
- /// This must be called after the header block has been completely decoded.
- ///
- /// true, if header block was ended, false otherwise.
- public bool EndHeaderBlock()
- {
- bool truncated = headerSize > maxHeaderSize;
- this.Reset();
- return truncated;
- }
-
- ///
- /// Set the maximum table size.
- /// If this is below the maximum size of the dynamic table used by the encoder,
- /// the beginning of the next header block MUST signal this change.
- ///
- /// Max header table size.
- public void SetMaxHeaderTableSize(int maxHeaderTableSize)
- {
- maxDynamicTableSize = maxHeaderTableSize;
- if (maxDynamicTableSize < encoderMaxDynamicTableSize) {
- // decoder requires less space than encoder
- // encoder MUST signal this change
- this.maxDynamicTableSizeChangeRequired = true;
- this.dynamicTable.SetCapacity(maxDynamicTableSize);
- }
- }
-
- ///
- /// Return the maximum table size.
- /// This is the maximum size allowed by both the encoder and the decoder.
- ///
- /// The max header table size.
- public int GetMaxHeaderTableSize()
- {
- return this.dynamicTable.Capacity;
- }
-
- ///
- /// Return the number of header fields in the dynamic table.
- /// Exposed for testing.
- ///
- int Length()
- {
- return this.dynamicTable.Length();
- }
-
- ///
- /// Return the size of the dynamic table.
- /// Exposed for testing.
- ///
- int Size()
- {
- return this.dynamicTable.Size;
- }
-
- ///
- /// Return the header field at the given index.
- /// Exposed for testing.
- ///
- /// The header field.
- /// Index.
- HeaderField GetHeaderField(int index)
- {
- return this.dynamicTable.GetEntry(index + 1);
- }
-
- private void SetDynamicTableSize(int dynamicTableSize)
- {
- if (dynamicTableSize > this.maxDynamicTableSize) {
- throw new IOException("invalid max dynamic table size");
- }
- this.encoderMaxDynamicTableSize = dynamicTableSize;
- this.maxDynamicTableSizeChangeRequired = false;
- this.dynamicTable.SetCapacity(dynamicTableSize);
- }
-
- private void ReadName(int index)
- {
- if (index <= StaticTable.Length) {
- HeaderField headerField = StaticTable.GetEntry(index);
- name = headerField.Name;
- } else if (index - StaticTable.Length <= this.dynamicTable.Length()) {
- HeaderField headerField = this.dynamicTable.GetEntry(index - StaticTable.Length);
- name = headerField.Name;
- } else {
- throw new IOException("illegal index value (" + index + ")");
- }
- }
-
- private void IndexHeader(int index, AddHeaderDelegate addHeaderDelegate)
- {
- if (index <= StaticTable.Length) {
- HeaderField headerField = StaticTable.GetEntry(index);
- this.AddHeader(addHeaderDelegate, headerField.Name, headerField.Value, false);
- } else if (index - StaticTable.Length <= this.dynamicTable.Length()) {
- HeaderField headerField = this.dynamicTable.GetEntry(index - StaticTable.Length);
- this.AddHeader(addHeaderDelegate, headerField.Name, headerField.Value, false);
- } else {
- throw new IOException("illegal index value (" + index + ")");
- }
- }
-
- private void InsertHeader(AddHeaderDelegate addHeaderDelegate, byte[] name, byte[] value, HPackUtil.IndexType indexType)
- {
- this.AddHeader(addHeaderDelegate, name, value, indexType == HPackUtil.IndexType.NEVER);
-
- switch(indexType) {
- case HPackUtil.IndexType.NONE:
- case HPackUtil.IndexType.NEVER:
- break;
-
- case HPackUtil.IndexType.INCREMENTAL:
- this.dynamicTable.Add(new HeaderField(name, value));
- break;
-
- default:
- throw new Exception("should not reach here");
- }
- }
-
- private void AddHeader(AddHeaderDelegate addHeaderDelegate, byte[] name, byte[] value, bool sensitive)
- {
- if (name.Length == 0) {
- throw new ArgumentException("name is empty");
- }
- long newSize = headerSize + name.Length + value.Length;
- if (newSize <= maxHeaderSize) {
- addHeaderDelegate (name, value, sensitive);
- headerSize = (int)newSize;
- } else {
- // truncation will be reported during endHeaderBlock
- headerSize = maxHeaderSize + 1;
- }
- }
-
- private bool ExceedsMaxHeaderSize(long size)
- {
- // Check new header size against max header size
- if (size + headerSize <= maxHeaderSize) {
- return false;
- }
-
- // truncation will be reported during endHeaderBlock
- headerSize = maxHeaderSize + 1;
- return true;
- }
-
- private byte[] ReadStringLiteral(BinaryReader input, int length)
- {
- byte[] buf = new byte[length];
- int lengthToRead = length;
- if (input.BaseStream.Length - input.BaseStream.Position < length) {
- lengthToRead = (int)input.BaseStream.Length - (int)input.BaseStream.Position;
- }
- int readBytes = input.Read(buf, 0, lengthToRead);
- if (readBytes != length) {
- throw DECOMPRESSION_EXCEPTION;
- }
-
- if (huffmanEncoded) {
- return Huffman.DECODER.Decode(buf);
- } else {
- return buf;
- }
- }
-
- // Unsigned Little Endian Base 128 Variable-Length Integer Encoding
- private static int DecodeULE128(BinaryReader input)
- {
- long markedPosition = input.BaseStream.Position;
- int result = 0;
- int shift = 0;
- while(shift < 32) {
- if (input.BaseStream.Length - input.BaseStream.Position == 0) {
- // Buffer does not contain entire integer,
- // reset reader index and return -1.
- input.BaseStream.Position = markedPosition;
- return -1;
- }
- sbyte b = input.ReadSByte();
- if (shift == 28 && (b & 0xF8) != 0) {
- break;
- }
- result |= (b & 0x7F) << shift;
- if ((b & 0x80) == 0) {
- return result;
- }
- shift += 7;
- }
- // Value exceeds Integer.MAX_VALUE
- input.BaseStream.Position = markedPosition;
- throw DECOMPRESSION_EXCEPTION;
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/DynamicTable.cs b/HttpTwo.HPack/DynamicTable.cs
deleted file mode 100644
index a13a1e2..0000000
--- a/HttpTwo.HPack/DynamicTable.cs
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-
-namespace HttpTwo.HPack
-{
- public class DynamicTable
- {
- // a circular queue of header fields
- HeaderField[] headerFields;
- int head;
- int tail;
- private int size;
- private int capacity = -1;
- // ensure setCapacity creates the array
-
- public int Capacity { get { return this.capacity; } }
-
- public int Size { get { return this.size; } }
-
- ///
- /// Creates a new dynamic table with the specified initial capacity.
- ///
- /// Initial capacity.
- public DynamicTable(int initialCapacity)
- {
- this.SetCapacity(initialCapacity);
- }
-
- ///
- /// Return the number of header fields in the dynamic table.
- ///
- public int Length()
- {
- int length;
- if (head < tail) {
- length = headerFields.Length - tail + head;
- } else {
- length = head - tail;
- }
- return length;
- }
-
- ///
- /// Return the current size of the dynamic table.
- /// This is the sum of the size of the entries.
- ///
- /// The size.
- public int GetSize()
- {
- return this.size;
- }
-
- ///
- /// Return the maximum allowable size of the dynamic table.
- ///
- /// The capacity.
- public int GetCapacity()
- {
- return capacity;
- }
-
- ///
- /// Return the header field at the given index.
- /// The first and newest entry is always at index 1,
- /// and the oldest entry is at the index length().
- ///
- /// The entry.
- /// Index.
- public HeaderField GetEntry(int index)
- {
- if (index <= 0 || index > this.Length()) {
- throw new IndexOutOfRangeException();
- }
- int i = head - index;
- if (i < 0) {
- return headerFields[i + headerFields.Length];
- } else {
- return headerFields[i];
- }
- }
-
- ///
- /// Add the header field to the dynamic table.
- /// Entries are evicted from the dynamic table until the size of the table
- /// and the new header field is less than or equal to the table's capacity.
- /// If the size of the new entry is larger than the table's capacity,
- /// the dynamic table will be cleared.
- ///
- /// Header.
- public void Add(HeaderField header)
- {
- int headerSize = header.Size;
- if (headerSize > capacity) {
- this.Clear();
- return;
- }
- while(size + headerSize > capacity) {
- this.Remove();
- }
- headerFields[head++] = header;
- size += header.Size;
- if (head == headerFields.Length) {
- head = 0;
- }
- }
-
- ///
- /// Remove and return the oldest header field from the dynamic table.
- ///
- public HeaderField Remove()
- {
- HeaderField removed = headerFields[tail];
- if (removed == null) {
- return null;
- }
- size -= removed.Size;
- headerFields[tail++] = null;
- if (tail == headerFields.Length) {
- tail = 0;
- }
- return removed;
- }
-
- ///
- /// Remove all entries from the dynamic table.
- ///
- public void Clear()
- {
- while(tail != head) {
- headerFields[tail++] = null;
- if (tail == headerFields.Length) {
- tail = 0;
- }
- }
- head = 0;
- tail = 0;
- size = 0;
- }
-
- ///
- /// Set the maximum size of the dynamic table.
- /// Entries are evicted from the dynamic table until the size of the table
- /// is less than or equal to the maximum size.
- ///
- /// Capacity.
- public void SetCapacity(int capacity)
- {
- if (capacity < 0) {
- throw new ArgumentException("Illegal Capacity: " + capacity);
- }
-
- // initially capacity will be -1 so init won't return here
- if (this.capacity == capacity) {
- return;
- }
- this.capacity = capacity;
-
- if (capacity == 0) {
- this.Clear();
- } else {
- // initially size will be 0 so remove won't be called
- while(size > capacity) {
- this.Remove();
- }
- }
-
- int maxEntries = capacity / HeaderField.HEADER_ENTRY_OVERHEAD;
- if (capacity % HeaderField.HEADER_ENTRY_OVERHEAD != 0) {
- maxEntries++;
- }
-
- // check if capacity change requires us to reallocate the array
- if (headerFields != null && headerFields.Length == maxEntries) {
- return;
- }
-
- HeaderField[] tmp = new HeaderField[maxEntries];
-
- // initially length will be 0 so there will be no copy
- int len = this.Length();
- int cursor = tail;
- for(int i = 0; i < len; i++) {
- HeaderField entry = headerFields[cursor++];
- tmp[i] = entry;
- if (cursor == headerFields.Length) {
- cursor = 0;
- }
- }
-
- this.tail = 0;
- this.head = tail + len;
- this.headerFields = tmp;
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/Encoder.cs b/HttpTwo.HPack/Encoder.cs
deleted file mode 100644
index 480414a..0000000
--- a/HttpTwo.HPack/Encoder.cs
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.IO;
-using System.Text;
-
-namespace HttpTwo.HPack
-{
- public class Encoder
- {
- private static int BUCKET_SIZE = 17;
- private static byte[] EMPTY = { };
-
- // for testing
- private bool useIndexing;
- private bool forceHuffmanOn;
- private bool forceHuffmanOff;
-
- // a linked hash map of header fields
- private HeaderEntry[] headerFields = new HeaderEntry[BUCKET_SIZE];
- private HeaderEntry head = new HeaderEntry(-1, EMPTY, EMPTY, int.MaxValue, null);
- private int size;
- private int capacity;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Max header table size.
- public Encoder(int maxHeaderTableSize)
- {
- this.Init(maxHeaderTableSize, true, false, false);
- }
-
- ///
- /// Initializes a new instance of the class.
- /// for testing only.
- ///
- /// Max header table size.
- /// If set to true use indexing.
- /// If set to true force huffman on.
- /// If set to true force huffman off.
- public Encoder(int maxHeaderTableSize, bool useIndexing, bool forceHuffmanOn, bool forceHuffmanOff)
- {
- this.Init(maxHeaderTableSize, useIndexing, forceHuffmanOn, forceHuffmanOff);
- }
-
- private void Init(int maxHeaderTableSize, bool useIndexing, bool forceHuffmanOn, bool forceHuffmanOff)
- {
- if (maxHeaderTableSize < 0) {
- throw new ArgumentException("Illegal Capacity: " + maxHeaderTableSize);
- }
- this.useIndexing = useIndexing;
- this.forceHuffmanOn = forceHuffmanOn;
- this.forceHuffmanOff = forceHuffmanOff;
- this.capacity = maxHeaderTableSize;
- head.Before = head.After = head;
- }
-
- public void EncodeHeader(BinaryWriter output, string name, string value)
- {
- this.EncodeHeader(output, name, value, false);
- }
-
- public void EncodeHeader(BinaryWriter output, string name, string value, bool sensitive)
- {
- this.EncodeHeader(output, Encoding.UTF8.GetBytes(name), Encoding.UTF8.GetBytes(value), sensitive);
- }
-
- public void EncodeHeader(BinaryWriter output, byte[] name, byte[] value)
- {
- this.EncodeHeader(output, name, value, false);
- }
-
- ///
- /// Encode the header field into the header block.
- ///
- /// Output.
- /// Name.
- /// Value.
- /// If set to true sensitive.
- public void EncodeHeader(BinaryWriter output, byte[] name, byte[] value, bool sensitive)
- {
- // If the header value is sensitive then it must never be indexed
- if (sensitive) {
- int nameIndex = this.GetNameIndex(name);
- this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NEVER, nameIndex);
- return;
- }
-
- // If the peer will only use the static table
- if (this.capacity == 0) {
- int staticTableIndex = StaticTable.GetIndex(name, value);
- if (staticTableIndex == -1) {
- int nameIndex = StaticTable.GetIndex(name);
- this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NONE, nameIndex);
- } else {
- Encoder.EncodeInteger(output, 0x80, 7, staticTableIndex);
- }
- return;
- }
-
- int headerSize = HeaderField.SizeOf(name, value);
-
- // If the headerSize is greater than the max table size then it must be encoded literally
- if (headerSize > this.capacity) {
- int nameIndex = this.GetNameIndex(name);
- this.EncodeLiteral(output, name, value, HPackUtil.IndexType.NONE, nameIndex);
- return;
- }
-
- HeaderEntry headerField = this.GetEntry(name, value);
- if (headerField != null) {
- int index = this.GetIndex(headerField.Index) + StaticTable.Length;
- // Section 6.1. Indexed Header Field Representation
- Encoder.EncodeInteger(output, 0x80, 7, index);
- } else {
- int staticTableIndex = StaticTable.GetIndex(name, value);
- if (staticTableIndex != -1) {
- // Section 6.1. Indexed Header Field Representation
- Encoder.EncodeInteger(output, 0x80, 7, staticTableIndex);
- } else {
- int nameIndex = this.GetNameIndex(name);
- if (useIndexing) {
- this.EnsureCapacity(headerSize);
- }
- var indexType = useIndexing ? HPackUtil.IndexType.INCREMENTAL : HPackUtil.IndexType.NONE;
- this.EncodeLiteral(output, name, value, indexType, nameIndex);
- if (useIndexing) {
- this.Add(name, value);
- }
- }
- }
- }
-
- ///
- /// Set the maximum table size.
- ///
- /// Output.
- /// Max header table size.
- public void SetMaxHeaderTableSize(BinaryWriter output, int maxHeaderTableSize)
- {
- if (maxHeaderTableSize < 0) {
- throw new ArgumentException("Illegal Capacity: " + maxHeaderTableSize);
- }
- if (this.capacity == maxHeaderTableSize) {
- return;
- }
- this.capacity = maxHeaderTableSize;
- this.EnsureCapacity(0);
- Encoder.EncodeInteger(output, 0x20, 5, maxHeaderTableSize);
- }
-
- ///
- /// Return the maximum table size.
- ///
- /// The max header table size.
- public int GetMaxHeaderTableSize()
- {
- return this.capacity;
- }
-
- ///
- /// Encode integer according to Section 5.1.
- ///
- /// Output.
- /// Mask.
- /// N.
- /// The index.
- private static void EncodeInteger(BinaryWriter output, int mask, int n, int i)
- {
- if (n < 0 || n > 8) {
- throw new ArgumentException("N: " + n);
- }
- int nbits = 0xFF >> (8 - n);
- if (i < nbits) {
- output.Write((byte)(mask | i));
- } else {
- output.Write((byte)(mask | nbits));
- int length = i - nbits;
- while(true) {
- if ((length & ~0x7F) == 0) {
- output.Write((byte)length);
- return;
- } else {
- output.Write((byte)((length & 0x7F) | 0x80));
- length >>= 7;
- }
- }
- }
- }
-
- ///
- /// Encode string literal according to Section 5.2.
- ///
- /// Output.
- /// String literal.
- private void EncodeStringLiteral(BinaryWriter output, byte[] stringLiteral)
- {
- int huffmanLength = Huffman.ENCODER.GetEncodedLength(stringLiteral);
- if ((huffmanLength < stringLiteral.Length && !forceHuffmanOff) || forceHuffmanOn) {
- Encoder.EncodeInteger(output, 0x80, 7, huffmanLength);
- Huffman.ENCODER.Encode(output, stringLiteral);
- } else {
- Encoder.EncodeInteger(output, 0x00, 7, stringLiteral.Length);
- output.Write(stringLiteral, 0, stringLiteral.Length);
- }
- }
-
- ///
- /// Encode literal header field according to Section 6.2.
- ///
- /// Output.
- /// Name.
- /// Value.
- /// Index type.
- /// Name index.
- private void EncodeLiteral(BinaryWriter output, byte[] name, byte[] value, HPackUtil.IndexType indexType, int nameIndex)
- {
- int mask;
- int prefixBits;
- switch(indexType) {
- case HPackUtil.IndexType.INCREMENTAL:
- mask = 0x40;
- prefixBits = 6;
- break;
-
- case HPackUtil.IndexType.NONE:
- mask = 0x00;
- prefixBits = 4;
- break;
-
- case HPackUtil.IndexType.NEVER:
- mask = 0x10;
- prefixBits = 4;
- break;
-
- default:
- throw new Exception("should not reach here");
- }
- Encoder.EncodeInteger(output, mask, prefixBits, nameIndex == -1 ? 0 : nameIndex);
- if (nameIndex == -1) {
- this.EncodeStringLiteral(output, name);
- }
- this.EncodeStringLiteral(output, value);
- }
-
- private int GetNameIndex(byte[] name)
- {
- int index = StaticTable.GetIndex(name);
- if (index == -1) {
- index = this.GetIndex(name);
- if (index >= 0) {
- index += StaticTable.Length;
- }
- }
- return index;
- }
-
- ///
- /// Ensure that the dynamic table has enough room to hold 'headerSize' more bytes.
- /// Removes the oldest entry from the dynamic table until sufficient space is available.
- ///
- /// Header size.
- private void EnsureCapacity(int headerSize)
- {
- while(this.size + headerSize > this.capacity) {
- int index = this.Length();
- if (index == 0) {
- break;
- }
- this.Remove();
- }
- }
-
- ///
- /// Return the number of header fields in the dynamic table.
- /// Exposed for testing.
- ///
- int Length()
- {
- return this.size == 0 ? 0 : this.head.After.Index - this.head.Before.Index + 1;
- }
-
- ///
- /// Return the size of the dynamic table.
- /// Exposed for testing.
- ///
- /// The size.
- int GetSize()
- {
- return this.size;
- }
-
- ///
- /// Return the header field at the given index.
- /// Exposed for testing.
- ///
- /// The header field.
- /// Index.
- HeaderField GetHeaderField(int index)
- {
- HeaderEntry entry = head;
- while(index-- >= 0) {
- entry = entry.Before;
- }
- return entry;
- }
-
- ///
- /// Returns the header entry with the lowest index value for the header field.
- /// Returns null if header field is not in the dynamic table.
- ///
- /// The entry.
- /// Name.
- /// Value.
- private HeaderEntry GetEntry(byte[] name, byte[] value)
- {
- if (this.Length() == 0 || name == null || value == null) {
- return null;
- }
- int h = Encoder.Hash(name);
- int i = Encoder.Index(h);
- for(HeaderEntry e = headerFields[i]; e != null; e = e.Next) {
- if (e.Hash == h && HPackUtil.Equals(name, e.Name) && HPackUtil.Equals(value, e.Value)) {
- return e;
- }
- }
- return null;
- }
-
- ///
- /// Returns the lowest index value for the header field name in the dynamic table.
- /// Returns -1 if the header field name is not in the dynamic table.
- ///
- /// The index.
- /// Name.
- private int GetIndex(byte[] name)
- {
- if (this.Length() == 0 || name == null) {
- return -1;
- }
- int h = Encoder.Hash(name);
- int i = Encoder.Index(h);
- int index = -1;
- for(HeaderEntry e = headerFields[i]; e != null; e = e.Next) {
- if (e.Hash == h && HPackUtil.Equals(name, e.Name)) {
- index = e.Index;
- break;
- }
- }
- return this.GetIndex(index);
- }
-
- ///
- /// Compute the index into the dynamic table given the index in the header entry.
- ///
- /// The index.
- /// Index.
- private int GetIndex(int index)
- {
- if (index == -1) {
- return index;
- }
- return index - head.Before.Index + 1;
- }
-
- ///
- /// Add the header field to the dynamic table.
- /// Entries are evicted from the dynamic table until the size of the table
- /// and the new header field is less than the table's capacity.
- /// If the size of the new entry is larger than the table's capacity,
- /// the dynamic table will be cleared.
- ///
- /// Name.
- /// Value.
- private void Add(byte[] name, byte[] value)
- {
- int headerSize = HeaderField.SizeOf(name, value);
-
- // Clear the table if the header field size is larger than the capacity.
- if (headerSize > this.capacity) {
- this.Clear();
- return;
- }
-
- // Evict oldest entries until we have enough capacity.
- while(this.size + headerSize > this.capacity) {
- this.Remove();
- }
-
- // Copy name and value that modifications of original do not affect the dynamic table.
- name.CopyTo(name, 0);
- value.CopyTo(value, 0);
-
- int h = Encoder.Hash(name);
- int i = Encoder.Index(h);
- HeaderEntry old = headerFields[i];
- HeaderEntry e = new HeaderEntry(h, name, value, head.Before.Index - 1, old);
- headerFields[i] = e;
- e.AddBefore(head);
- this.size += headerSize;
- }
-
- ///
- /// Remove and return the oldest header field from the dynamic table.
- ///
- private HeaderField Remove()
- {
- if (this.size == 0) {
- return null;
- }
- HeaderEntry eldest = head.After;
- int h = eldest.Hash;
- int i = Encoder.Index(h);
- HeaderEntry prev = headerFields[i];
- HeaderEntry e = prev;
- while(e != null) {
- HeaderEntry next = e.Next;
- if (e == eldest) {
- if (prev == eldest) {
- headerFields[i] = next;
- } else {
- prev.Next = next;
- }
- eldest.Remove();
- this.size -= eldest.Size;
- return eldest;
- }
- prev = e;
- e = next;
- }
- return null;
- }
-
- ///
- /// Remove all entries from the dynamic table.
- ///
- private void Clear()
- {
- for(int i = 0; i < headerFields.Length; i++) {
- headerFields[i] = null;
- }
- head.Before = head.After = head;
- this.size = 0;
- }
-
- ///
- /// Returns the hash code for the given header field name.
- ///
- /// true if hash name; otherwise, false.
- /// Name.
- private static int Hash(byte[] name)
- {
- int h = 0;
- for(int i = 0; i < name.Length; i++) {
- h = 31 * h + name[i];
- }
- if (h > 0) {
- return h;
- } else if (h == int.MinValue) {
- return int.MaxValue;
- } else {
- return -h;
- }
- }
-
- ///
- /// Returns the index into the hash table for the hash code h.
- ///
- /// The height.
- private static int Index(int h)
- {
- return h % BUCKET_SIZE;
- }
-
- ///
- /// A linked hash map HeaderField entry.
- ///
- private class HeaderEntry : HeaderField
- {
- // These fields comprise the doubly linked list used for iteration.
- private HeaderEntry before, after;
-
- // These fields comprise the chained list for header fields with the same hash.
- private HeaderEntry next;
- private int hash;
-
- // This is used to compute the index in the dynamic table.
- private int index;
-
- public HeaderEntry Before { get { return this.before; } set { this.before = value; } }
-
- public HeaderEntry After { get { return this.after; } set { this.after = value; } }
-
- public HeaderEntry Next { get { return this.next; } set { this.next = value; } }
-
- public int Hash { get { return this.hash; } }
-
- public int Index { get { return this.index; } }
-
- ///
- /// Creates new entry.
- ///
- /// Hash.
- /// Name.
- /// Value.
- /// Index.
- /// Next.
- public HeaderEntry(int hash, byte[] name, byte[] value, int index, HeaderEntry next) : base(name, value)
- {
- this.index = index;
- this.hash = hash;
- this.next = next;
- }
-
- ///
- /// Removes this entry from the linked list.
- ///
- public void Remove()
- {
- before.after = after;
- after.before = before;
- }
-
- ///
- /// Inserts this entry before the specified existing entry in the list.
- ///
- /// Existing entry.
- public void AddBefore(HeaderEntry existingEntry)
- {
- after = existingEntry;
- before = existingEntry.before;
- before.after = this;
- after.before = this;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/HPackUtil.cs b/HttpTwo.HPack/HPackUtil.cs
deleted file mode 100644
index a6677fa..0000000
--- a/HttpTwo.HPack/HPackUtil.cs
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.Text;
-
-namespace HttpTwo.HPack
-{
- public class HPackUtil
- {
- ///
- /// A string compare that doesn't leak timing information.
- ///
- /// S1.
- /// S2.
- public static bool Equals(byte[] s1, byte[] s2)
- {
- if (s1.Length != s2.Length) {
- return false;
- }
- int c = 0;
- for(int i = 0; i < s1.Length; i++) {
- c |= (s1[i] ^ s2[i]);
- }
- return c == 0;
- }
-
- ///
- /// Checks that the specified object reference is not {@code null}.
- ///
- /// The non null.
- /// Object.
- public static object RequireNonNull(object obj)
- {
- if (obj == null) {
- throw new NullReferenceException();
- }
- return obj;
- }
-
- // Section 6.2. Literal Header Field Representation
- public enum IndexType
- {
- INCREMENTAL,
- // Section 6.2.1. Literal Header Field with Incremental Indexing
- NONE,
- // Section 6.2.2. Literal Header Field without Indexing
- NEVER
- // Section 6.2.3. Literal Header Field never Indexed
- }
-
- // Appendix B: Huffman Codes
- // http://tools.ietf.org/html/rfc7541#appendix-B
- public static int[] HUFFMAN_CODES = {
- 0x1ff8,
- 0x7fffd8,
- 0xfffffe2,
- 0xfffffe3,
- 0xfffffe4,
- 0xfffffe5,
- 0xfffffe6,
- 0xfffffe7,
- 0xfffffe8,
- 0xffffea,
- 0x3ffffffc,
- 0xfffffe9,
- 0xfffffea,
- 0x3ffffffd,
- 0xfffffeb,
- 0xfffffec,
- 0xfffffed,
- 0xfffffee,
- 0xfffffef,
- 0xffffff0,
- 0xffffff1,
- 0xffffff2,
- 0x3ffffffe,
- 0xffffff3,
- 0xffffff4,
- 0xffffff5,
- 0xffffff6,
- 0xffffff7,
- 0xffffff8,
- 0xffffff9,
- 0xffffffa,
- 0xffffffb,
- 0x14,
- 0x3f8,
- 0x3f9,
- 0xffa,
- 0x1ff9,
- 0x15,
- 0xf8,
- 0x7fa,
- 0x3fa,
- 0x3fb,
- 0xf9,
- 0x7fb,
- 0xfa,
- 0x16,
- 0x17,
- 0x18,
- 0x0,
- 0x1,
- 0x2,
- 0x19,
- 0x1a,
- 0x1b,
- 0x1c,
- 0x1d,
- 0x1e,
- 0x1f,
- 0x5c,
- 0xfb,
- 0x7ffc,
- 0x20,
- 0xffb,
- 0x3fc,
- 0x1ffa,
- 0x21,
- 0x5d,
- 0x5e,
- 0x5f,
- 0x60,
- 0x61,
- 0x62,
- 0x63,
- 0x64,
- 0x65,
- 0x66,
- 0x67,
- 0x68,
- 0x69,
- 0x6a,
- 0x6b,
- 0x6c,
- 0x6d,
- 0x6e,
- 0x6f,
- 0x70,
- 0x71,
- 0x72,
- 0xfc,
- 0x73,
- 0xfd,
- 0x1ffb,
- 0x7fff0,
- 0x1ffc,
- 0x3ffc,
- 0x22,
- 0x7ffd,
- 0x3,
- 0x23,
- 0x4,
- 0x24,
- 0x5,
- 0x25,
- 0x26,
- 0x27,
- 0x6,
- 0x74,
- 0x75,
- 0x28,
- 0x29,
- 0x2a,
- 0x7,
- 0x2b,
- 0x76,
- 0x2c,
- 0x8,
- 0x9,
- 0x2d,
- 0x77,
- 0x78,
- 0x79,
- 0x7a,
- 0x7b,
- 0x7ffe,
- 0x7fc,
- 0x3ffd,
- 0x1ffd,
- 0xffffffc,
- 0xfffe6,
- 0x3fffd2,
- 0xfffe7,
- 0xfffe8,
- 0x3fffd3,
- 0x3fffd4,
- 0x3fffd5,
- 0x7fffd9,
- 0x3fffd6,
- 0x7fffda,
- 0x7fffdb,
- 0x7fffdc,
- 0x7fffdd,
- 0x7fffde,
- 0xffffeb,
- 0x7fffdf,
- 0xffffec,
- 0xffffed,
- 0x3fffd7,
- 0x7fffe0,
- 0xffffee,
- 0x7fffe1,
- 0x7fffe2,
- 0x7fffe3,
- 0x7fffe4,
- 0x1fffdc,
- 0x3fffd8,
- 0x7fffe5,
- 0x3fffd9,
- 0x7fffe6,
- 0x7fffe7,
- 0xffffef,
- 0x3fffda,
- 0x1fffdd,
- 0xfffe9,
- 0x3fffdb,
- 0x3fffdc,
- 0x7fffe8,
- 0x7fffe9,
- 0x1fffde,
- 0x7fffea,
- 0x3fffdd,
- 0x3fffde,
- 0xfffff0,
- 0x1fffdf,
- 0x3fffdf,
- 0x7fffeb,
- 0x7fffec,
- 0x1fffe0,
- 0x1fffe1,
- 0x3fffe0,
- 0x1fffe2,
- 0x7fffed,
- 0x3fffe1,
- 0x7fffee,
- 0x7fffef,
- 0xfffea,
- 0x3fffe2,
- 0x3fffe3,
- 0x3fffe4,
- 0x7ffff0,
- 0x3fffe5,
- 0x3fffe6,
- 0x7ffff1,
- 0x3ffffe0,
- 0x3ffffe1,
- 0xfffeb,
- 0x7fff1,
- 0x3fffe7,
- 0x7ffff2,
- 0x3fffe8,
- 0x1ffffec,
- 0x3ffffe2,
- 0x3ffffe3,
- 0x3ffffe4,
- 0x7ffffde,
- 0x7ffffdf,
- 0x3ffffe5,
- 0xfffff1,
- 0x1ffffed,
- 0x7fff2,
- 0x1fffe3,
- 0x3ffffe6,
- 0x7ffffe0,
- 0x7ffffe1,
- 0x3ffffe7,
- 0x7ffffe2,
- 0xfffff2,
- 0x1fffe4,
- 0x1fffe5,
- 0x3ffffe8,
- 0x3ffffe9,
- 0xffffffd,
- 0x7ffffe3,
- 0x7ffffe4,
- 0x7ffffe5,
- 0xfffec,
- 0xfffff3,
- 0xfffed,
- 0x1fffe6,
- 0x3fffe9,
- 0x1fffe7,
- 0x1fffe8,
- 0x7ffff3,
- 0x3fffea,
- 0x3fffeb,
- 0x1ffffee,
- 0x1ffffef,
- 0xfffff4,
- 0xfffff5,
- 0x3ffffea,
- 0x7ffff4,
- 0x3ffffeb,
- 0x7ffffe6,
- 0x3ffffec,
- 0x3ffffed,
- 0x7ffffe7,
- 0x7ffffe8,
- 0x7ffffe9,
- 0x7ffffea,
- 0x7ffffeb,
- 0xffffffe,
- 0x7ffffec,
- 0x7ffffed,
- 0x7ffffee,
- 0x7ffffef,
- 0x7fffff0,
- 0x3ffffee,
- 0x3fffffff // EOS
- };
-
- public static byte[] HUFFMAN_CODE_LENGTHS = {
- 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
- 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
- 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
- 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
- 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
- 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
- 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
- 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
- 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
- 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
- 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
- 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
- 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
- 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
- 30 // EOS
- };
-
- public static int HUFFMAN_EOS = 256;
-
- private HPackUtil()
- {
- // utility class
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/HeaderDelegate.cs b/HttpTwo.HPack/HeaderDelegate.cs
deleted file mode 100644
index e0c7bc1..0000000
--- a/HttpTwo.HPack/HeaderDelegate.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-namespace HttpTwo.HPack
-{
- ///
- /// EmitHeader is called by the decoder during header field emission.
- /// The name and value byte arrays must not be modified.
- ///
- /// Name.
- /// Value.
- /// If set to true sensitive.
- public delegate void AddHeaderDelegate (byte[] name, byte[] value, bool sensitive);
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/HeaderField.cs b/HttpTwo.HPack/HeaderField.cs
deleted file mode 100644
index 395178d..0000000
--- a/HttpTwo.HPack/HeaderField.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.Text;
-
-namespace HttpTwo.HPack
-{
- public class HeaderField : IComparable
- {
- private byte[] name;
- private byte[] value;
-
- // Section 4.1. Calculating Table Size
- // The additional 32 octets account for an estimated
- // overhead associated with the structure.
- public static int HEADER_ENTRY_OVERHEAD = 32;
-
- public byte[] Name { get { return this.name; } }
-
- public byte[] Value { get { return this.value; } }
-
- public int Size { get { return this.name.Length + this.value.Length + HEADER_ENTRY_OVERHEAD; } }
-
- // This constructor can only be used if name and value are ISO-8859-1 encoded.
- public HeaderField(string name, string value)
- {
- this.name = Encoding.UTF8.GetBytes(name);
- this.value = Encoding.UTF8.GetBytes(value);
- }
-
- public HeaderField(byte[] name, byte[] value)
- {
- this.name = (byte[])HPackUtil.RequireNonNull(name);
- this.value = (byte[])HPackUtil.RequireNonNull(value);
- }
-
- public static int SizeOf(byte[] name, byte[] value)
- {
- return name.Length + value.Length + HEADER_ENTRY_OVERHEAD;
- }
-
- public int CompareTo(HeaderField anotherHeaderField)
- {
- int ret = this.CompareTo(name, anotherHeaderField.name);
- if (ret == 0) {
- ret = this.CompareTo(value, anotherHeaderField.value);
- }
- return ret;
- }
-
- private int CompareTo(byte[] s1, byte[] s2)
- {
- int len1 = s1.Length;
- int len2 = s2.Length;
- int lim = Math.Min(len1, len2);
-
- int k = 0;
- while(k < lim) {
- byte b1 = s1[k];
- byte b2 = s2[k];
- if (b1 != b2) {
- return b1 - b2;
- }
- k++;
- }
- return len1 - len2;
- }
-
- public override bool Equals(Object obj)
- {
- if (obj == this) {
- return true;
- }
- if (!(obj is HeaderField)) {
- return false;
- }
- HeaderField other = (HeaderField)obj;
- bool nameEquals = HPackUtil.Equals(name, other.name);
- bool valueEquals = HPackUtil.Equals(value, other.value);
- return nameEquals && valueEquals;
- }
-
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
-
- public override String ToString()
- {
- return String.Format("{0}: {1}", Encoding.UTF8.GetString(this.name), Encoding.UTF8.GetString(this.value));
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/HttpTwo.HPack.csproj b/HttpTwo.HPack/HttpTwo.HPack.csproj
deleted file mode 100644
index 8b2f48a..0000000
--- a/HttpTwo.HPack/HttpTwo.HPack.csproj
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
- Debug
- AnyCPU
- {C75A83BB-7EF1-4CDB-8C52-9E6E3E11341D}
- Library
- HttpTwo.HPack
- HttpTwo.HPack
- v4.5
-
-
- true
- full
- false
- bin\Debug
- DEBUG;
- prompt
- 4
- false
-
-
- full
- true
- bin\Release
- prompt
- 4
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/HttpTwo.HPack/Huffman.cs b/HttpTwo.HPack/Huffman.cs
deleted file mode 100644
index 38d10e6..0000000
--- a/HttpTwo.HPack/Huffman.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-namespace HttpTwo.HPack
-{
- public class Huffman
- {
- ///
- /// Huffman Decoder
- ///
- public static readonly HuffmanDecoder DECODER = new HuffmanDecoder(HPackUtil.HUFFMAN_CODES, HPackUtil.HUFFMAN_CODE_LENGTHS);
-
- ///
- /// Huffman Encoder
- ///
- public static readonly HuffmanEncoder ENCODER = new HuffmanEncoder(HPackUtil.HUFFMAN_CODES, HPackUtil.HUFFMAN_CODE_LENGTHS);
-
- private Huffman()
- {
- // utility class
- }
- }
-}
diff --git a/HttpTwo.HPack/HuffmanDecoder.cs b/HttpTwo.HPack/HuffmanDecoder.cs
deleted file mode 100644
index d2c397a..0000000
--- a/HttpTwo.HPack/HuffmanDecoder.cs
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.IO;
-
-namespace HttpTwo.HPack
-{
- public class HuffmanDecoder
- {
- private static IOException EOS_DECODED = new IOException("EOS Decoded");
- private static IOException INVALID_PADDING = new IOException("Invalid Padding");
-
- private Node root;
-
- ///
- /// Creates a new Huffman decoder with the specified Huffman coding.
- ///
- /// the Huffman codes indexed by symbol
- /// the length of each Huffman code
- public HuffmanDecoder(int[] codes, byte[] lengths)
- {
- if (codes.Length != 257 || codes.Length != lengths.Length) {
- throw new ArgumentException("invalid Huffman coding");
- }
- this.root = BuildTree(codes, lengths);
- }
-
- ///
- /// Decompresses the given Huffman coded string literal.
- ///
- /// the string literal to be decoded
- /// the output stream for the compressed data
- /// throws IOException if an I/O error occurs. In particular, an IOException may be thrown if the output stream has been closed.
- public byte[] Decode(byte[] buf)
- {
- using(var baos = new MemoryStream()) {
- Node node = root;
- int current = 0;
- int bits = 0;
- for(int i = 0; i < buf.Length; i++) {
- int b = buf[i] & 0xFF;
- current = (current << 8) | b;
- bits += 8;
- while(bits >= 8) {
- int c = (current >> (bits - 8)) & 0xFF;
- node = node.Children[c];
- bits -= node.Bits;
- if (node.IsTerminal()) {
- if (node.Symbol == HPackUtil.HUFFMAN_EOS) {
- throw EOS_DECODED;
- }
- baos.Write(new byte[] { (byte)node.Symbol }, 0, 1);
- node = root;
- }
- }
- }
-
- while(bits > 0) {
- int c = (current << (8 - bits)) & 0xFF;
- node = node.Children[c];
- if (node.IsTerminal() && node.Bits <= bits) {
- bits -= node.Bits;
- baos.Write(new byte[] { (byte)node.Symbol }, 0, 1);
- node = root;
- } else {
- break;
- }
- }
-
- // Section 5.2. String Literal Representation
- // Padding not corresponding to the most significant bits of the code
- // for the EOS symbol (0xFF) MUST be treated as a decoding error.
- int mask = (1 << bits) - 1;
- if ((current & mask) != mask) {
- throw INVALID_PADDING;
- }
-
- return baos.ToArray();
- }
- }
-
- public class Node
- {
- private int symbol;
- // terminal nodes have a symbol
- private int bits;
- // number of bits matched by the node
- private Node[] children;
- // internal nodes have children
-
- public int Symbol { get { return this.symbol; } }
-
- public int Bits { get { return this.bits; } }
-
- public Node[] Children { get { return this.children; } }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public Node()
- {
- symbol = 0;
- bits = 8;
- children = new Node[256];
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// the symbol the node represents
- /// the number of bits matched by this node
- public Node(int symbol, int bits)
- {
- //assert(bits > 0 && bits <= 8);
- this.symbol = symbol;
- this.bits = bits;
- children = null;
- }
-
- public bool IsTerminal()
- {
- return children == null;
- }
- }
-
- private static Node BuildTree(int[] codes, byte[] lengths)
- {
- Node root = new Node();
- for(int i = 0; i < codes.Length; i++) {
- Insert(root, i, codes[i], lengths[i]);
- }
- return root;
- }
-
- private static void Insert(Node root, int symbol, int code, byte length)
- {
- // traverse tree using the most significant bytes of code
- Node current = root;
- while(length > 8) {
- if (current.IsTerminal()) {
- throw new InvalidDataException("invalid Huffman code: prefix not unique");
- }
- length -= 8;
- int i = (code >> length) & 0xFF;
- if (current.Children[i] == null) {
- current.Children[i] = new Node();
- }
- current = current.Children[i];
- }
-
- Node terminal = new Node(symbol, length);
- int shift = 8 - length;
- int start = (code << shift) & 0xFF;
- int end = 1 << shift;
- for(int i = start; i < start + end; i++) {
- current.Children[i] = terminal;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/HuffmanEncoder.cs b/HttpTwo.HPack/HuffmanEncoder.cs
deleted file mode 100644
index cc12ae6..0000000
--- a/HttpTwo.HPack/HuffmanEncoder.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.IO;
-
-namespace HttpTwo.HPack
-{
- public class HuffmanEncoder
- {
- private int[] codes;
- private byte[] lengths;
-
- ///
- /// Creates a new Huffman encoder with the specified Huffman coding.
- ///
- /// the Huffman codes indexed by symbol
- /// the length of each Huffman code
- public HuffmanEncoder(int[] codes, byte[] lengths)
- {
- this.codes = codes;
- this.lengths = lengths;
- }
-
- ///
- /// Compresses the input string literal using the Huffman coding.
- ///
- /// the output stream for the compressed data
- /// the string literal to be Huffman encoded
- /// if an I/O error occurs.
- ///
- public void Encode(BinaryWriter output, byte[] data)
- {
- this.Encode(output, data, 0, data.Length);
- }
-
- ///
- /// Compresses the input string literal using the Huffman coding.
- ///
- /// the output stream for the compressed data
- /// the string literal to be Huffman encoded
- /// the start offset in the data
- /// the number of bytes to encode
- /// if an I/O error occurs. In particular, an IOException may be thrown if the output stream has been closed.
- public void Encode(BinaryWriter output, byte[] data, int off, int len)
- {
- if (output == null) {
- throw new NullReferenceException("out");
- } else if (data == null) {
- throw new NullReferenceException("data");
- } else if (off < 0 || len < 0 || (off + len) < 0 || off > data.Length || (off + len) > data.Length) {
- throw new IndexOutOfRangeException();
- } else if (len == 0) {
- return;
- }
-
- long current = 0;
- int n = 0;
-
- for(int i = 0; i < len; i++) {
- int b = data[off + i] & 0xFF;
- uint code = (uint)this.codes[b];
- int nbits = lengths[b];
-
- current <<= nbits;
- current |= code;
- n += nbits;
-
- while(n >= 8) {
- n -= 8;
- output.Write(((byte)(current >> n)));
- }
- }
-
- if (n > 0) {
- current <<= (8 - n);
- current |= (uint)(0xFF >> n); // this should be EOS symbol
- output.Write((byte)current);
- }
- }
-
- ///
- /// Returns the number of bytes required to Huffman encode the input string literal.
- ///
- /// the number of bytes required to Huffman encode data
- /// the string literal to be Huffman encoded
- public int GetEncodedLength(byte[] data)
- {
- if (data == null) {
- throw new NullReferenceException("data");
- }
- long len = 0;
- foreach(byte b in data) {
- len += lengths[b & 0xFF];
- }
- return (int)((len + 7) >> 3);
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.HPack/Properties/AssemblyInfo.cs b/HttpTwo.HPack/Properties/AssemblyInfo.cs
deleted file mode 100644
index 818d11d..0000000
--- a/HttpTwo.HPack/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-
-[assembly: AssemblyTitle ("HPack")]
-[assembly: AssemblyDescription ("")]
-[assembly: AssemblyConfiguration ("")]
-[assembly: AssemblyCompany ("")]
-[assembly: AssemblyProduct ("")]
-[assembly: AssemblyCopyright ("redth")]
-[assembly: AssemblyTrademark ("")]
-[assembly: AssemblyCulture ("")]
-
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-
-[assembly: AssemblyVersion ("1.0.*")]
-
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/HttpTwo.HPack/StaticTable.cs b/HttpTwo.HPack/StaticTable.cs
deleted file mode 100644
index 0fb7235..0000000
--- a/HttpTwo.HPack/StaticTable.cs
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2015 Ringo Leese
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Collections;
-using System.Text;
-
-namespace HttpTwo.HPack
-{
- public static class StaticTable
- {
- ///
- /// The static table
- /// Appendix A: Static Table
- ///
- ///
- private static List STATIC_TABLE = new List() {
- /* 1 */new HeaderField(":authority", String.Empty),
- /* 2 */new HeaderField(":method", "GET"),
- /* 3 */new HeaderField(":method", "POST"),
- /* 4 */new HeaderField(":path", "/"),
- /* 5 */new HeaderField(":path", "/index.html"),
- /* 6 */new HeaderField(":scheme", "http"),
- /* 7 */new HeaderField(":scheme", "https"),
- /* 8 */new HeaderField(":status", "200"),
- /* 9 */new HeaderField(":status", "204"),
- /* 10 */new HeaderField(":status", "206"),
- /* 11 */new HeaderField(":status", "304"),
- /* 12 */new HeaderField(":status", "400"),
- /* 13 */new HeaderField(":status", "404"),
- /* 14 */new HeaderField(":status", "500"),
- /* 15 */new HeaderField("accept-charset", String.Empty),
- /* 16 */new HeaderField("accept-encoding", "gzip, deflate"),
- /* 17 */new HeaderField("accept-language", String.Empty),
- /* 18 */new HeaderField("accept-ranges", String.Empty),
- /* 19 */new HeaderField("accept", String.Empty),
- /* 20 */new HeaderField("access-control-allow-origin", String.Empty),
- /* 21 */new HeaderField("age", String.Empty),
- /* 22 */new HeaderField("allow", String.Empty),
- /* 23 */new HeaderField("authorization", String.Empty),
- /* 24 */new HeaderField("cache-control", String.Empty),
- /* 25 */new HeaderField("content-disposition", String.Empty),
- /* 26 */new HeaderField("content-encoding", String.Empty),
- /* 27 */new HeaderField("content-language", String.Empty),
- /* 28 */new HeaderField("content-length", String.Empty),
- /* 29 */new HeaderField("content-location", String.Empty),
- /* 30 */new HeaderField("content-range", String.Empty),
- /* 31 */new HeaderField("content-type", String.Empty),
- /* 32 */new HeaderField("cookie", String.Empty),
- /* 33 */new HeaderField("date", String.Empty),
- /* 34 */new HeaderField("etag", String.Empty),
- /* 35 */new HeaderField("expect", String.Empty),
- /* 36 */new HeaderField("expires", String.Empty),
- /* 37 */new HeaderField("from", String.Empty),
- /* 38 */new HeaderField("host", String.Empty),
- /* 39 */new HeaderField("if-match", String.Empty),
- /* 40 */new HeaderField("if-modified-since", String.Empty),
- /* 41 */new HeaderField("if-none-match", String.Empty),
- /* 42 */new HeaderField("if-range", String.Empty),
- /* 43 */new HeaderField("if-unmodified-since", String.Empty),
- /* 44 */new HeaderField("last-modified", String.Empty),
- /* 45 */new HeaderField("link", String.Empty),
- /* 46 */new HeaderField("location", String.Empty),
- /* 47 */new HeaderField("max-forwards", String.Empty),
- /* 48 */new HeaderField("proxy-authenticate", String.Empty),
- /* 49 */new HeaderField("proxy-authorization", String.Empty),
- /* 50 */new HeaderField("range", String.Empty),
- /* 51 */new HeaderField("referer", String.Empty),
- /* 52 */new HeaderField("refresh", String.Empty),
- /* 53 */new HeaderField("retry-after", String.Empty),
- /* 54 */new HeaderField("server", String.Empty),
- /* 55 */new HeaderField("set-cookie", String.Empty),
- /* 56 */new HeaderField("strict-transport-security", String.Empty),
- /* 57 */new HeaderField("transfer-encoding", String.Empty),
- /* 58 */new HeaderField("user-agent", String.Empty),
- /* 59 */new HeaderField("vary", String.Empty),
- /* 60 */new HeaderField("via", String.Empty),
- /* 61 */new HeaderField("www-authenticate", String.Empty)
- };
-
- private static Dictionary STATIC_INDEX_BY_NAME = CreateMap();
-
- ///
- /// The number of header fields in the static table.
- ///
- /// The length.
- public static int Length { get { return STATIC_TABLE.Count; } }
-
- ///
- /// Return the header field at the given index value.
- ///
- /// The entry.
- /// Index.
- public static HeaderField GetEntry(int index)
- {
- return STATIC_TABLE[index - 1];
- }
-
- ///
- /// Returns the lowest index value for the given header field name in the static table.
- /// Returns -1 if the header field name is not in the static table.
- ///
- /// The index.
- /// Name.
- public static int GetIndex(byte[] name)
- {
- string nameString = Encoding.UTF8.GetString(name);
- if (!STATIC_INDEX_BY_NAME.ContainsKey(nameString)) {
- return -1;
- }
- return STATIC_INDEX_BY_NAME[nameString];
- }
-
- ///
- /// Returns the index value for the given header field in the static table.
- /// Returns -1 if the header field is not in the static table.
- ///
- /// The index.
- /// Name.
- /// Value.
- public static int GetIndex(byte[] name, byte[] value)
- {
- int index = GetIndex(name);
- if (index == -1) {
- return -1;
- }
-
- // Note this assumes all entries for a given header field are sequential.
- while(index <= StaticTable.Length) {
- HeaderField entry = GetEntry(index);
- if (!HPackUtil.Equals(name, entry.Name)) {
- break;
- }
- if (HPackUtil.Equals(value, entry.Value)) {
- return index;
- }
- index++;
- }
-
- return -1;
- }
-
- ///
- /// create a map of header name to index value to allow quick lookup
- ///
- /// The map.
- private static Dictionary CreateMap()
- {
- int length = STATIC_TABLE.Count;
- var ret = new Dictionary(length);
-
- // Iterate through the static table in reverse order to
- // save the smallest index for a given name in the map.
- for(int index = length; index > 0; index--) {
- HeaderField entry = GetEntry(index);
- string name = Encoding.UTF8.GetString(entry.Name);
- ret[name] = index;
- }
- return ret;
- }
- }
-}
\ No newline at end of file
diff --git a/HttpTwo.Tests/HttpTests.cs b/HttpTwo.Tests/HttpTests.cs
index a63ed57..4115d7c 100644
--- a/HttpTwo.Tests/HttpTests.cs
+++ b/HttpTwo.Tests/HttpTests.cs
@@ -3,6 +3,7 @@
using System.Net.Http;
using System.Collections.Specialized;
using System.Threading;
+using System.Threading.Tasks;
using HttpTwo.Internal;
namespace HttpTwo.Tests
@@ -14,7 +15,7 @@ public class HttpTests
NodeHttp2Runner node;
- [TestFixtureSetUp]
+ [OneTimeSetUp]
public void Setup ()
{
// Setup logger
@@ -30,7 +31,7 @@ public void Setup ()
}
}
- [TestFixtureTearDown]
+ [OneTimeTearDown]
public void Teardown ()
{
if (UseInternalHttpRunner)
@@ -38,31 +39,33 @@ public void Teardown ()
}
[Test]
- public async void Get_Single_Html_Page ()
+ public async Task Get_Single_Html_Page ()
{
var http2MsgHandler = new Http2MessageHandler ();
var http = new HttpClient (http2MsgHandler);
var data = await http.GetStringAsync ("http://localhost:8999/index.html");
- Assert.IsNotNullOrEmpty (data);
+ Assert.IsNotNull (data);
+ Assert.IsNotEmpty(data);
Assert.IsTrue (data.Contains ("Hello World"));
}
//[Test]
- public async void Get_Single_Html_Page_Https ()
+ public async Task Get_Single_Html_Page_Https ()
{
var http2MsgHandler = new Http2MessageHandler ();
var http = new HttpClient (http2MsgHandler);
var data = await http.GetStringAsync ("https://localhost:8999/index.html");
- Assert.IsNotNullOrEmpty (data);
+ Assert.IsNotNull (data);
+ Assert.IsNotEmpty(data);
Assert.IsTrue (data.Contains ("Hello World"));
}
[Test]
- public async void Get_Multiple_Html_Pages ()
+ public async Task Get_Multiple_Html_Pages ()
{
var http2MsgHandler = new Http2MessageHandler ();
var http = new HttpClient (http2MsgHandler);
@@ -70,14 +73,15 @@ public async void Get_Multiple_Html_Pages ()
for (int i = 0; i < 3; i++) {
var data = await http.GetStringAsync ("http://localhost:8999/index.html");
- Assert.IsNotNullOrEmpty (data);
+ Assert.IsNotNull (data);
+ Assert.IsNotEmpty(data);
Assert.IsTrue (data.Contains ("Hello World"));
}
}
[Test]
- public async void Settings_Disable_Push_Promise ()
+ public async Task Settings_Disable_Push_Promise ()
{
var url = new Uri ("http://localhost:8999/index.html");
var settings = new Http2ConnectionSettings (url) { DisablePushPromise = true };
@@ -109,7 +113,7 @@ public async void Settings_Disable_Push_Promise ()
[Test]
- public async void Get_Send_Headers_With_Continuation ()
+ public async Task Get_Send_Headers_With_Continuation ()
{
var uri = new Uri ("http://localhost:8999/index.html");
var http = new Http2Client (uri);
@@ -123,12 +127,13 @@ public async void Get_Send_Headers_With_Continuation ()
var data = System.Text.Encoding.ASCII.GetString (response.Body);
- Assert.IsNotNullOrEmpty (data);
+ Assert.IsNotNull (data);
+ Assert.IsNotEmpty(data);
Assert.IsTrue (data.Contains ("Hello World"));
}
[Test]
- public async void Ping ()
+ public async Task Ping ()
{
var uri = new Uri ("http://localhost:8999/index.html");
var http = new Http2Client (uri);
@@ -144,7 +149,7 @@ public async void Ping ()
}
[Test]
- public async void GoAway ()
+ public async Task GoAway ()
{
var uri = new Uri ("http://localhost:8999/index.html");
var http = new Http2Client (uri);
diff --git a/HttpTwo.Tests/HttpTwo.Tests.csproj b/HttpTwo.Tests/HttpTwo.Tests.csproj
index bda0989..14914cb 100644
--- a/HttpTwo.Tests/HttpTwo.Tests.csproj
+++ b/HttpTwo.Tests/HttpTwo.Tests.csproj
@@ -1,57 +1,46 @@
-
-
-
- Debug
- AnyCPU
- {DD2208F9-C8C1-430A-AB17-5A657733A029}
- Library
- HttpTwo.Tests
- HttpTwo.Tests
- v4.5
-
-
- true
- full
- false
- bin\Debug
- DEBUG;TRACE;
- prompt
- 4
- false
-
-
- true
- bin\Release
- prompt
- 4
- false
- TRACE;
-
-
-
-
- ..\packages\NUnit.2.6.4\lib\nunit.framework.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {DC2F25D9-75BE-4C67-B41D-84B738A16B9F}
- HttpTwo
-
-
- {C75A83BB-7EF1-4CDB-8C52-9E6E3E11341D}
- HttpTwo.HPack
-
-
-
\ No newline at end of file
+
+
+ Debug
+ AnyCPU
+ {DD2208F9-C8C1-430A-AB17-5A657733A029}
+ Library
+ HttpTwo.Tests
+ HttpTwo.Tests
+ net6.0;net462
+ false
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;TRACE;
+ prompt
+ 4
+ false
+
+
+ true
+ bin\Release
+ prompt
+ 4
+ false
+ TRACE;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {DC2F25D9-75BE-4C67-B41D-84B738A16B9F}
+ HttpTwo
+
+
+
diff --git a/HttpTwo.Tests/NodeHttp2Runner.cs b/HttpTwo.Tests/NodeHttp2Runner.cs
index 4f39739..6172780 100644
--- a/HttpTwo.Tests/NodeHttp2Runner.cs
+++ b/HttpTwo.Tests/NodeHttp2Runner.cs
@@ -17,7 +17,7 @@ public void StartServer ()
return;
// HTTP2_PLAIN=true HTTP2_LOG=trace HTTP2_LOG_DATA=1 node ./example/server.js
- var scriptPath = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "..", "..", "node-http2", "example", "server.js");
+ var scriptPath = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "node-http2", "example", "server.js");
process = new Process ();
process.StartInfo = new ProcessStartInfo ("node", "\"" + scriptPath + "\"");
diff --git a/HttpTwo.Tests/node-http2/package-lock.json b/HttpTwo.Tests/node-http2/package-lock.json
new file mode 100644
index 0000000..cf591c3
--- /dev/null
+++ b/HttpTwo.Tests/node-http2/package-lock.json
@@ -0,0 +1,2780 @@
+{
+ "name": "http2",
+ "version": "3.2.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "http2",
+ "version": "3.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "bunyan": "^1.5.1"
+ },
+ "devDependencies": {
+ "bunyan": "*",
+ "chai": "*",
+ "docco": "*",
+ "istanbul": "*",
+ "mocha": "*"
+ },
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/abbrev": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+ "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==",
+ "dev": true
+ },
+ "node_modules/amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.4.2"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
+ "dev": true
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "node_modules/bunyan": {
+ "version": "1.8.15",
+ "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz",
+ "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==",
+ "dev": true,
+ "engines": [
+ "node >=0.10.0"
+ ],
+ "bin": {
+ "bunyan": "bin/bunyan"
+ },
+ "optionalDependencies": {
+ "dtrace-provider": "~0.8",
+ "moment": "^2.19.3",
+ "mv": "~2",
+ "safe-json-stringify": "~1"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chai": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
+ "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+ "dev": true,
+ "dependencies": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^3.0.1",
+ "get-func-name": "^2.0.0",
+ "loupe": "^2.3.1",
+ "pathval": "^1.1.1",
+ "type-detect": "^4.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/chalk/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "dependencies": {
+ "type-detect": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/docco": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/docco/-/docco-0.9.1.tgz",
+ "integrity": "sha512-B1jUzcAc4AmicWUnmPTxUGM2lqJ11X4DiLUXyhzUVb7A1NNGTSNo3LtGzhHMyRAuJyxrHwHiOCDGuE/n9xRhmA==",
+ "dev": true,
+ "dependencies": {
+ "commander": "~ 8.3.0",
+ "fs-extra": "~ 10.0.0",
+ "highlight.js": "~ 11.3.1",
+ "marked": "~ 4.0.3",
+ "underscore": "~ 1.13.1"
+ },
+ "bin": {
+ "docco": "bin/docco"
+ },
+ "engines": {
+ "node": ">=0.2.0"
+ }
+ },
+ "node_modules/dtrace-provider": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
+ "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "dependencies": {
+ "nan": "^2.14.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+ "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==",
+ "dev": true,
+ "dependencies": {
+ "esprima": "^2.7.1",
+ "estraverse": "^1.9.1",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=0.12.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.2.0"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+ "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz",
+ "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==",
+ "dev": true,
+ "dependencies": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.7",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.0",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/handlebars/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/highlight.js": {
+ "version": "11.3.1",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.3.1.tgz",
+ "integrity": "sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/istanbul": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
+ "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==",
+ "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "1.0.x",
+ "async": "1.x",
+ "escodegen": "1.8.x",
+ "esprima": "2.7.x",
+ "glob": "^5.0.15",
+ "handlebars": "^4.0.1",
+ "js-yaml": "3.x",
+ "mkdirp": "0.5.x",
+ "nopt": "3.x",
+ "once": "1.x",
+ "resolve": "1.1.x",
+ "supports-color": "^3.1.0",
+ "which": "^1.1.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "istanbul": "lib/cli.js"
+ }
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/js-yaml/node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
+ "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==",
+ "dev": true,
+ "dependencies": {
+ "get-func-name": "^2.0.0"
+ }
+ },
+ "node_modules/marked": {
+ "version": "4.0.19",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.19.tgz",
+ "integrity": "sha512-rgQF/OxOiLcvgUAj1Q1tAf4Bgxn5h5JZTp04Fx4XUkVhs7B+7YA9JEWJhJpoO8eJt8MkZMwqLCNeNqj1bCREZQ==",
+ "dev": true,
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/mocha": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz",
+ "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mochajs"
+ }
+ },
+ "node_modules/mocha/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mocha/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/mv": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
+ "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "mkdirp": "~0.5.1",
+ "ncp": "~2.0.0",
+ "rimraf": "~2.4.0"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/nan": {
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
+ "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/ncp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
+ "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==",
+ "dev": true,
+ "optional": true,
+ "bin": {
+ "ncp": "bin/ncp"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node_modules/nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pathval": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==",
+ "dev": true
+ },
+ "node_modules/rimraf": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
+ "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "glob": "^6.0.1"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
+ "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-json-stringify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz",
+ "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+ "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "amdefine": ">=0.0.4"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.17.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
+ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
+ "dev": true,
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/underscore": {
+ "version": "1.13.6",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
+ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
+ "dev": true
+ },
+ "node_modules/universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true
+ },
+ "node_modules/workerpool": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+ "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==",
+ "dev": true
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==",
+ "dev": true,
+ "optional": true
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "bunyan": {
+ "version": "1.8.15",
+ "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz",
+ "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==",
+ "dev": true,
+ "requires": {
+ "dtrace-provider": "~0.8",
+ "moment": "^2.19.3",
+ "mv": "~2",
+ "safe-json-stringify": "~1"
+ }
+ },
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true
+ },
+ "chai": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
+ "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+ "dev": true,
+ "requires": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^3.0.1",
+ "get-func-name": "^2.0.0",
+ "loupe": "^2.3.1",
+ "pathval": "^1.1.1",
+ "type-detect": "^4.0.5"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ }
+ },
+ "cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true
+ },
+ "deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "^4.0.0"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true
+ },
+ "docco": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/docco/-/docco-0.9.1.tgz",
+ "integrity": "sha512-B1jUzcAc4AmicWUnmPTxUGM2lqJ11X4DiLUXyhzUVb7A1NNGTSNo3LtGzhHMyRAuJyxrHwHiOCDGuE/n9xRhmA==",
+ "dev": true,
+ "requires": {
+ "commander": "~ 8.3.0",
+ "fs-extra": "~ 10.0.0",
+ "highlight.js": "~ 11.3.1",
+ "marked": "~ 4.0.3",
+ "underscore": "~ 1.13.1"
+ }
+ },
+ "dtrace-provider": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
+ "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "^2.14.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "escodegen": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+ "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==",
+ "dev": true,
+ "requires": {
+ "esprima": "^2.7.1",
+ "estraverse": "^1.9.1",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1",
+ "source-map": "~0.2.0"
+ }
+ },
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==",
+ "dev": true
+ },
+ "estraverse": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+ "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz",
+ "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
+ "dev": true
+ },
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==",
+ "dev": true,
+ "requires": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "handlebars": {
+ "version": "4.7.7",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.0",
+ "source-map": "^0.6.1",
+ "uglify-js": "^3.1.4",
+ "wordwrap": "^1.0.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==",
+ "dev": true
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true
+ },
+ "highlight.js": {
+ "version": "11.3.1",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.3.1.tgz",
+ "integrity": "sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true
+ },
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "istanbul": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
+ "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==",
+ "dev": true,
+ "requires": {
+ "abbrev": "1.0.x",
+ "async": "1.x",
+ "escodegen": "1.8.x",
+ "esprima": "2.7.x",
+ "glob": "^5.0.15",
+ "handlebars": "^4.0.1",
+ "js-yaml": "3.x",
+ "mkdirp": "0.5.x",
+ "nopt": "3.x",
+ "once": "1.x",
+ "resolve": "1.1.x",
+ "supports-color": "^3.1.0",
+ "which": "^1.1.1",
+ "wordwrap": "^1.0.0"
+ }
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ }
+ }
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
+ "loupe": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
+ "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==",
+ "dev": true,
+ "requires": {
+ "get-func-name": "^2.0.0"
+ }
+ },
+ "marked": {
+ "version": "4.0.19",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.19.tgz",
+ "integrity": "sha512-rgQF/OxOiLcvgUAj1Q1tAf4Bgxn5h5JZTp04Fx4XUkVhs7B+7YA9JEWJhJpoO8eJt8MkZMwqLCNeNqj1bCREZQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.6"
+ }
+ },
+ "mocha": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz",
+ "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ }
+ }
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "dev": true,
+ "optional": true
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "mv": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
+ "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "mkdirp": "~0.5.1",
+ "ncp": "~2.0.0",
+ "rimraf": "~2.4.0"
+ }
+ },
+ "nan": {
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
+ "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
+ "dev": true,
+ "optional": true
+ },
+ "nanoid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+ "dev": true
+ },
+ "ncp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
+ "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==",
+ "dev": true,
+ "optional": true
+ },
+ "neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
+ "dev": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "requires": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ }
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "pathval": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "dev": true
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
+ "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^6.0.1"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
+ "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ },
+ "safe-json-stringify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz",
+ "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==",
+ "dev": true,
+ "optional": true
+ },
+ "serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+ "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^1.0.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.17.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
+ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
+ "dev": true,
+ "optional": true
+ },
+ "underscore": {
+ "version": "1.13.6",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
+ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
+ "dev": true
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true
+ },
+ "workerpool": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true
+ },
+ "yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ }
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
+ }
+ }
+}
diff --git a/HttpTwo.Tests/packages.config b/HttpTwo.Tests/packages.config
deleted file mode 100644
index c714ef3..0000000
--- a/HttpTwo.Tests/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/HttpTwo.nuspec b/HttpTwo.nuspec
index 1afe1bd..8b81eaa 100644
--- a/HttpTwo.nuspec
+++ b/HttpTwo.nuspec
@@ -4,24 +4,23 @@
HttpTwo
$version$
HttpTwo
- Redth
- Redth
- http://www.apache.org/licenses/LICENSE-2.0.txt
- https://github.com/Redth/HttpTwo
- https://raw.githubusercontent.com/Redth/HttpTwo/master/HttpTwo-Icon.png
+ Redth,Neio,silentdth
+ Redth,Neio,silentdth
+ https://github.com/neio/HttpTwo
+ https://raw.githubusercontent.com/neio/HttpTwo/master/HttpTwo-Icon.png
false
HTTP/2 C# Client Side Implementation
HTTP/2 C# Client Side Implementation
- 2012-2016 Redth
+ 2012-2022 Redth,Neio,silentdth
en-US
HTTP, HTTP2, HTTP/2, HTTPTWO, Http Two, HTTP 2, HTTP.2, HTTP_2, HTTP-2
-
-
+
+
diff --git a/HttpTwo.sln b/HttpTwo.sln
index 210aa90..193d339 100644
--- a/HttpTwo.sln
+++ b/HttpTwo.sln
@@ -1,8 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpTwo.HPack", "HttpTwo.HPack\HttpTwo.HPack.csproj", "{C75A83BB-7EF1-4CDB-8C52-9E6E3E11341D}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpTwo", "HttpTwo\HttpTwo.csproj", "{DC2F25D9-75BE-4C67-B41D-84B738A16B9F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpTwo.Tests", "HttpTwo.Tests\HttpTwo.Tests.csproj", "{DD2208F9-C8C1-430A-AB17-5A657733A029}"
@@ -13,10 +11,6 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C75A83BB-7EF1-4CDB-8C52-9E6E3E11341D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C75A83BB-7EF1-4CDB-8C52-9E6E3E11341D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C75A83BB-7EF1-4CDB-8C52-9E6E3E11341D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C75A83BB-7EF1-4CDB-8C52-9E6E3E11341D}.Release|Any CPU.Build.0 = Release|Any CPU
{DC2F25D9-75BE-4C67-B41D-84B738A16B9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC2F25D9-75BE-4C67-B41D-84B738A16B9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC2F25D9-75BE-4C67-B41D-84B738A16B9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -26,4 +20,7 @@ Global
{DD2208F9-C8C1-430A-AB17-5A657733A029}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD2208F9-C8C1-430A-AB17-5A657733A029}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
EndGlobal
diff --git a/HttpTwo/Frames/Frame.cs b/HttpTwo/Frames/Frame.cs
index 468001f..409b17d 100644
--- a/HttpTwo/Frames/Frame.cs
+++ b/HttpTwo/Frames/Frame.cs
@@ -71,11 +71,11 @@ public uint Length {
public abstract FrameType Type { get; }
- public virtual byte Flags { get; protected set; } = 0x0;
+ public virtual byte Flags { get; protected set; }
public virtual uint StreamIdentifier { get; set; }
- public virtual IEnumerable Payload { get; }
+ public virtual IEnumerable Payload { get { return null; } }
uint? payloadLength;
public uint PayloadLength {
diff --git a/HttpTwo/Frames/HeadersFrame.cs b/HttpTwo/Frames/HeadersFrame.cs
index 6bcf15a..3c100b5 100644
--- a/HttpTwo/Frames/HeadersFrame.cs
+++ b/HttpTwo/Frames/HeadersFrame.cs
@@ -46,7 +46,7 @@ public ushort Weight {
public bool EndHeaders { get;set; }
public bool Priority { get;set; }
public byte[] HeaderBlockFragment { get; set; }
- public uint StreamDependency { get; set; } = 0;
+ public uint StreamDependency { get; set; }
public override FrameType Type {
get { return FrameType.Headers; }
diff --git a/HttpTwo/Frames/PriorityFrame.cs b/HttpTwo/Frames/PriorityFrame.cs
index f89eb5d..a8d7bb4 100644
--- a/HttpTwo/Frames/PriorityFrame.cs
+++ b/HttpTwo/Frames/PriorityFrame.cs
@@ -27,7 +27,7 @@ public ushort Weight {
}
}
- public uint StreamDependency { get; set; } = 0;
+ public uint StreamDependency { get; set; }
// type=0x1
public override FrameType Type {
diff --git a/HttpTwo/Frames/PushPromiseFrame.cs b/HttpTwo/Frames/PushPromiseFrame.cs
index 5e0e90a..2a19b43 100644
--- a/HttpTwo/Frames/PushPromiseFrame.cs
+++ b/HttpTwo/Frames/PushPromiseFrame.cs
@@ -30,7 +30,7 @@ public ushort PadLength {
public byte[] HeaderBlockFragment { get;set; }
- public uint StreamDependency { get; set; } = 0;
+ public uint StreamDependency { get; set; }
public override FrameType Type {
get { return FrameType.PushPromise; }
diff --git a/HttpTwo/Http2Client.cs b/HttpTwo/Http2Client.cs
index e109f6a..3fa9e22 100644
--- a/HttpTwo/Http2Client.cs
+++ b/HttpTwo/Http2Client.cs
@@ -1,307 +1,333 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Security.Cryptography.X509Certificates;
-using System.Threading;
-using System.Threading.Tasks;
-using HttpTwo.Internal;
-
-namespace HttpTwo
-{
- public class Http2Client
- {
- readonly Http2Connection connection;
- readonly IStreamManager streamManager;
- IFlowControlManager flowControlManager;
-
- public Http2Client (Uri uri, X509CertificateCollection certificates = null, IStreamManager streamManager = null, IFlowControlManager flowControlManager = null)
- : this (new Http2ConnectionSettings (uri, certificates), streamManager, flowControlManager)
- {
- }
-
- public Http2Client (string url, X509CertificateCollection certificates = null, IStreamManager streamManager = null, IFlowControlManager flowControlManager = null)
- : this (new Http2ConnectionSettings (url, certificates), streamManager, flowControlManager)
- {
- }
-
- public Http2Client (Http2ConnectionSettings connectionSettings, IStreamManager streamManager = null, IFlowControlManager flowControlManager = null)
- {
- this.flowControlManager = flowControlManager ?? new FlowControlManager ();
- this.streamManager = streamManager ?? new StreamManager (this.flowControlManager);
- this.ConnectionSettings = connectionSettings;
-
- connection = new Http2Connection (ConnectionSettings, this.streamManager, this.flowControlManager);
- }
-
- public Http2ConnectionSettings ConnectionSettings { get; private set; }
-
- public IStreamManager StreamManager { get { return streamManager; } }
- public IFlowControlManager FlowControlManager { get { return flowControlManager; } }
-
- public async Task Connect ()
- {
- await connection.Connect ().ConfigureAwait (false);
- }
-
- public async Task Post (Uri uri, NameValueCollection headers = null, byte[] data = null)
- {
- return await Send (uri, HttpMethod.Post, headers, data).ConfigureAwait (false);
- }
-
- public async Task Post (Uri uri, NameValueCollection headers = null, Stream data = null)
- {
- return await Send (uri, HttpMethod.Post, headers, data).ConfigureAwait (false);
- }
-
- public async Task Send (Uri uri, HttpMethod method, NameValueCollection headers = null, byte[] data = null)
- {
- MemoryStream ms = null;
-
- if (data != null)
- ms = new MemoryStream (data);
-
- return await Send (new CancellationToken (), uri, method, headers, ms).ConfigureAwait (false);
- }
-
- public async Task Send (Uri uri, HttpMethod method, NameValueCollection headers = null, Stream data = null)
- {
- return await Send (new CancellationToken (), uri, method, headers, data).ConfigureAwait (false);
- }
-
- public async Task Send (CancellationToken cancelToken, Uri uri, HttpMethod method, NameValueCollection headers = null, Stream data = null)
- {
- var semaphoreClose = new SemaphoreSlim(0);
-
- await connection.Connect ().ConfigureAwait (false);
-
- var stream = await streamManager.Get ().ConfigureAwait (false);
- stream.OnFrameReceived += async (frame) =>
- {
- // Check for an end of stream state
- if (stream.State == StreamState.HalfClosedRemote || stream.State == StreamState.Closed)
- semaphoreClose.Release ();
- };
-
- var sentEndOfStream = false;
-
- var allHeaders = new NameValueCollection ();
- allHeaders.Add (":method", method.Method.ToUpperInvariant ());
- allHeaders.Add (":path", uri.PathAndQuery);
- allHeaders.Add (":scheme", uri.Scheme);
- allHeaders.Add (":authority", uri.Authority);
- if (headers != null && headers.Count > 0)
- allHeaders.Add (headers);
-
- var headerData = Util.PackHeaders (allHeaders, connection.Settings.HeaderTableSize);
-
- var numFrames = (int)Math.Ceiling ((double)headerData.Length / (double)connection.Settings.MaxFrameSize);
-
- for (int i = 0; i < numFrames; i++) {
- // First item is headers frame, others are continuation
- IFrameContainsHeaders frame = (i == 0) ?
- (IFrameContainsHeaders)new HeadersFrame (stream.StreamIdentifer)
- : (IFrameContainsHeaders)new ContinuationFrame (stream.StreamIdentifer);
-
- // Set end flag if this is the last item
- if (i == numFrames - 1)
- frame.EndHeaders = true;
-
- var maxFrameSize = connection.Settings.MaxFrameSize;
-
- var amt = maxFrameSize;
- if ( i * maxFrameSize + amt > headerData.Length)
- amt = (uint)headerData.Length - (uint)(i * maxFrameSize);
- frame.HeaderBlockFragment = new byte[amt];
- Array.Copy (headerData, i * maxFrameSize, frame.HeaderBlockFragment, 0, amt);
-
- // If we won't s end
- if (data == null && frame is HeadersFrame) {
- sentEndOfStream = true;
- (frame as HeadersFrame).EndStream = true;
- }
-
- await connection.QueueFrame (frame).ConfigureAwait (false);
- }
-
- if (data != null) {
- var supportsPosLength = true; // Keep track of if we threw exceptions trying pos/len of stream
-
- // Break stream up into data frames within allowed size
- var dataFrameBuffer = new byte[connection.Settings.MaxFrameSize];
- while (true) {
-
- var rd = await data.ReadAsync (dataFrameBuffer, 0, dataFrameBuffer.Length).ConfigureAwait (false);
-
- if (rd <= 0)
- break;
-
- // Make a new data frame with a buffer the size we read
- var dataFrame = new DataFrame (stream.StreamIdentifer);
- dataFrame.Data = new byte[rd];
- // Copy over the data we read
- Array.Copy(dataFrameBuffer, 0, dataFrame.Data, 0, rd);
-
- try {
- // See if the stream supports Length / Position to try and detect EOS
- // we also want to see if we previously had an exception trying this
- // and not try again if we did, since throwing exceptions every single
- // read operation is wasteful
- if (supportsPosLength && data.Position >= data.Length) {
- dataFrame.EndStream = true;
- sentEndOfStream = true;
- }
- } catch {
- supportsPosLength = false;
- sentEndOfStream = false;
- }
-
- await connection.QueueFrame (dataFrame).ConfigureAwait (false);
- }
- }
-
- // Send an empty frame with end of stream flag
- if (!sentEndOfStream)
- await connection.QueueFrame(new DataFrame(stream.StreamIdentifer) { EndStream = true }).ConfigureAwait(false);
-
- if (!await semaphoreClose.WaitAsync (ConnectionSettings.ConnectionTimeout, cancelToken).ConfigureAwait (false))
- throw new TimeoutException ();
-
- var responseData = new List ();
- var rxHeaderData = new List ();
-
- foreach (var f in stream.ReceivedFrames) {
- if (f.Type == FrameType.Headers || f.Type == FrameType.Continuation) {
- // Get the header data and add it to our buffer
- var fch = (IFrameContainsHeaders)f;
- if (fch.HeaderBlockFragment != null && fch.HeaderBlockFragment.Length > 0)
- rxHeaderData.AddRange (fch.HeaderBlockFragment);
- } else if (f.Type == FrameType.PushPromise) {
- // TODO: In the future we need to implement PushPromise beyond grabbing header data
- var fch = (IFrameContainsHeaders)f;
- if (fch.HeaderBlockFragment != null && fch.HeaderBlockFragment.Length > 0)
- rxHeaderData.AddRange (fch.HeaderBlockFragment);
- } else if (f.Type == FrameType.Data) {
- responseData.AddRange ((f as DataFrame).Data);
- } else if (f.Type == FrameType.GoAway) {
- var fga = f as GoAwayFrame;
- if (fga != null && fga.AdditionalDebugData != null && fga.AdditionalDebugData.Length > 0)
- responseData.AddRange (fga.AdditionalDebugData);
- }
- }
-
- var responseHeaders = Util.UnpackHeaders (rxHeaderData.ToArray (),
- connection.Settings.MaxHeaderListSize.HasValue ? (int)connection.Settings.MaxHeaderListSize.Value : 8192,
- (int)connection.Settings.HeaderTableSize);
-
- var strStatus = "500";
- if (responseHeaders [":status"] != null)
- strStatus = responseHeaders [":status"];
-
- var statusCode = HttpStatusCode.OK;
- Enum.TryParse (strStatus, out statusCode);
-
- // Remove the stream from being tracked since we're done with it
- await streamManager.Cleanup (stream.StreamIdentifer).ConfigureAwait (false);
-
- // Send a WINDOW_UPDATE frame to release our stream's data count
- // TODO: Eventually need to do this on the stream itself too (if it's open)
- await connection.FreeUpWindowSpace ().ConfigureAwait (false);
-
- return new Http2Response {
- Status = statusCode,
- Stream = stream,
- Headers = responseHeaders,
- Body = responseData.ToArray ()
- };
- }
-
- public async Task Ping (byte[] opaqueData, CancellationToken cancelToken)
- {
- if (opaqueData == null || opaqueData.Length <= 0)
- throw new ArgumentNullException ("opaqueData");
-
- await connection.Connect ().ConfigureAwait (false);
-
- var semaphoreWait = new SemaphoreSlim (0);
- var opaqueDataMatch = false;
-
- var connectionStream = await streamManager.Get (0).ConfigureAwait (false);
-
- Http2Stream.FrameReceivedDelegate frameRxAction;
- frameRxAction = new Http2Stream.FrameReceivedDelegate (frame => {
- var pf = frame as PingFrame;
- if (pf != null) {
- opaqueDataMatch = pf.Ack && pf.OpaqueData != null && pf.OpaqueData.SequenceEqual (opaqueData);
- semaphoreWait.Release ();
- }
- });
-
- // Wire up the event to listen for ping response
- connectionStream.OnFrameReceived += frameRxAction;
-
- // Construct ping request
- var pingFrame = new PingFrame ();
- pingFrame.OpaqueData = new byte[opaqueData.Length];
- opaqueData.CopyTo (pingFrame.OpaqueData, 0);
-
- // Send ping
- await connection.QueueFrame (pingFrame).ConfigureAwait (false);
-
- // Wait for either a ping response or timeout
- await semaphoreWait.WaitAsync (cancelToken).ConfigureAwait (false);
-
- // Cleanup the event
- connectionStream.OnFrameReceived -= frameRxAction;
-
- return opaqueDataMatch;
- }
-
- public async Task Disconnect ()
- {
- return await Disconnect (Timeout.InfiniteTimeSpan).ConfigureAwait (false);
- }
-
- public async Task Disconnect (TimeSpan timeout)
- {
- var connectionStream = await streamManager.Get (0).ConfigureAwait (false);
-
- var semaphoreWait = new SemaphoreSlim (0);
- var cancelTokenSource = new CancellationTokenSource ();
- var sentGoAway = false;
-
- var sentDelegate = new Http2Stream.FrameSentDelegate (frame => {
- if (frame.Type == FrameType.GoAway) {
- sentGoAway = true;
- semaphoreWait.Release ();
- }
- });
-
- connectionStream.OnFrameSent += sentDelegate;
-
- await connection.QueueFrame (new GoAwayFrame ()).ConfigureAwait (false);
-
- if (timeout != Timeout.InfiniteTimeSpan)
- cancelTokenSource.CancelAfter (timeout);
-
- await semaphoreWait.WaitAsync (cancelTokenSource.Token).ConfigureAwait (false);
-
- connectionStream.OnFrameSent -= sentDelegate;
-
- connection.Disconnect ();
-
- return sentGoAway;
- }
-
- public class Http2Response
- {
- public HttpStatusCode Status { get; set; }
- public Http2Stream Stream { get; set; }
- public NameValueCollection Headers { get;set; }
- public byte[] Body { get;set; }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+using System.Threading.Tasks;
+using HttpTwo.Internal;
+
+namespace HttpTwo
+{
+ public class Http2Client
+ {
+ Http2Connection connection;
+ readonly IStreamManager streamManager;
+ IFlowControlManager flowControlManager;
+
+ public Http2Client (Uri uri, X509CertificateCollection certificates = null, IStreamManager streamManager = null, IFlowControlManager flowControlManager = null)
+ : this (new Http2ConnectionSettings (uri, certificates), streamManager, flowControlManager)
+ {
+ }
+
+ public Http2Client (string url, X509CertificateCollection certificates = null, IStreamManager streamManager = null, IFlowControlManager flowControlManager = null)
+ : this (new Http2ConnectionSettings (url, certificates), streamManager, flowControlManager)
+ {
+ }
+
+ public Http2Client (Http2ConnectionSettings connectionSettings, IStreamManager streamManager = null, IFlowControlManager flowControlManager = null)
+ {
+ this.flowControlManager = flowControlManager ?? new FlowControlManager ();
+ this.streamManager = streamManager ?? new StreamManager (this.flowControlManager);
+ this.ConnectionSettings = connectionSettings;
+ }
+
+ public Http2ConnectionSettings ConnectionSettings { get; private set; }
+
+ public IStreamManager StreamManager { get { return streamManager; } }
+ public IFlowControlManager FlowControlManager { get { return flowControlManager; } }
+
+ public async Task Connect()
+ {
+ if (connection != null && !connection.IsConnected())
+ {
+ connection.Disconnect();
+ connection = null;
+ }
+
+ if (connection == null)
+ {
+ streamManager.Reset();
+ connection = new Http2Connection(ConnectionSettings, this.streamManager, this.flowControlManager);
+ await connection.Connect().ConfigureAwait(false);
+ }
+
+ }
+
+ public async Task Post (Uri uri, NameValueCollection headers = null, byte[] data = null)
+ {
+ return await Send (uri, HttpMethod.Post, headers, data).ConfigureAwait (false);
+ }
+
+ public async Task Post (Uri uri, NameValueCollection headers = null, Stream data = null)
+ {
+ return await Send (uri, HttpMethod.Post, headers, data).ConfigureAwait (false);
+ }
+
+ public async Task Send (Uri uri, HttpMethod method, NameValueCollection headers = null, byte[] data = null)
+ {
+ MemoryStream ms = null;
+
+ if (data != null)
+ ms = new MemoryStream (data);
+
+ return await Send (new CancellationToken (), uri, method, headers, ms).ConfigureAwait (false);
+ }
+
+ public async Task Send (Uri uri, HttpMethod method, NameValueCollection headers = null, Stream data = null)
+ {
+ return await Send (new CancellationToken (), uri, method, headers, data).ConfigureAwait (false);
+ }
+
+ public async Task Send (CancellationToken cancelToken, Uri uri, HttpMethod method, NameValueCollection headers = null, Stream data = null)
+ {
+ var semaphoreClose = new SemaphoreSlim(0);
+
+ await Connect();
+
+ List