diff --git a/.pubnub.yml b/.pubnub.yml
index 0ce28efd2..a95340763 100644
--- a/.pubnub.yml
+++ b/.pubnub.yml
@@ -1,8 +1,13 @@
name: c-sharp
-version: "7.3.14"
+version: "7.3.15"
schema: 1
scm: github.com/pubnub/c-sharp
changelog:
+ - date: 2025-07-03
+ version: v7.3.15
+ changes:
+ - type: feature
+ text: "Implemented an in-house CBOR solution for ParseToken() handling to reduce total SDK+dependencies size."
- date: 2025-06-25
version: v7.3.14
changes:
@@ -919,7 +924,7 @@ features:
- QUERY-PARAM
supported-platforms:
-
- version: Pubnub 'C#' 7.3.14
+ version: Pubnub 'C#' 7.3.15
platforms:
- Windows 10 and up
- Windows Server 2008 and up
@@ -930,7 +935,7 @@ supported-platforms:
- .Net Framework 4.6.1+
- .Net Framework 6.0
-
- version: PubnubPCL 'C#' 7.3.14
+ version: PubnubPCL 'C#' 7.3.15
platforms:
- Xamarin.Android
- Xamarin.iOS
@@ -950,7 +955,7 @@ supported-platforms:
- .Net Core
- .Net 6.0
-
- version: PubnubUWP 'C#' 7.3.14
+ version: PubnubUWP 'C#' 7.3.15
platforms:
- Windows Phone 10
- Universal Windows Apps
@@ -974,7 +979,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: Pubnub
- location: https://github.com/pubnub/c-sharp/releases/tag/v7.3.14.0
+ location: https://github.com/pubnub/c-sharp/releases/tag/v7.3.15.0
requires:
-
name: ".Net"
@@ -1257,7 +1262,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: PubNubPCL
- location: https://github.com/pubnub/c-sharp/releases/tag/v7.3.14.0
+ location: https://github.com/pubnub/c-sharp/releases/tag/v7.3.15.0
requires:
-
name: ".Net Core"
@@ -1616,7 +1621,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: PubnubUWP
- location: https://github.com/pubnub/c-sharp/releases/tag/v7.3.14.0
+ location: https://github.com/pubnub/c-sharp/releases/tag/v7.3.15.0
requires:
-
name: "Universal Windows Platform Development"
diff --git a/CHANGELOG b/CHANGELOG
index 72c6128fd..64725daf1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+v7.3.15 - July 03 2025
+-----------------------------
+- Added: implemented an in-house CBOR solution for ParseToken() handling to reduce total SDK+dependencies size.
+
v7.3.14 - June 25 2025
-----------------------------
- Modified: updated log type from Error to Warn for TaskCanceledException.
diff --git a/src/Api/PubnubApi/CBOR.cs b/src/Api/PubnubApi/CBOR.cs
new file mode 100644
index 000000000..075cf6efa
--- /dev/null
+++ b/src/Api/PubnubApi/CBOR.cs
@@ -0,0 +1,509 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace PubnubApi
+{
+ ///
+ /// A simple not-all-covering implementation of CBOR serialisation/deserialisation for internal Pubnub ParseToken() usage
+ /// Converted to C# from https://github.com/seba-aln/CBORCodec
+ ///
+ internal static class CBOR
+ {
+ private const byte TYPE_MASK = 0b11100000;
+ private const byte ADDITIONAL_MASK = 0b00011111;
+
+ public const byte TYPE_UNSIGNED_INT = 0b00000000;
+ public const byte TYPE_NEGATIVE_INT = 0b00100000;
+ public const byte TYPE_BYTE_STRING = 0b01000000;
+ public const byte TYPE_TEXT_STRING = 0b01100000;
+ public const byte TYPE_ARRAY = 0b10000000;
+ public const byte TYPE_HASHMAP = 0b10100000;
+ public const byte TYPE_FLOAT = 0b11100000;
+
+ private const byte ADDITIONAL_LENGTH_1B = 24;
+ private const byte ADDITIONAL_LENGTH_2B = 25;
+ private const byte ADDITIONAL_LENGTH_4B = 26;
+ private const byte ADDITIONAL_LENGTH_8B = 27;
+
+ private const byte ADDITIONAL_TYPE_INDEFINITE = 31;
+
+ private const byte INDEFINITE_BREAK = 0b11111111;
+
+ private static readonly byte[] additionalLength = {
+ ADDITIONAL_LENGTH_1B,
+ ADDITIONAL_LENGTH_2B,
+ ADDITIONAL_LENGTH_4B,
+ ADDITIONAL_LENGTH_8B,
+ };
+
+ private static readonly Dictionary additionalLengthBytes = new Dictionary
+ {
+ { ADDITIONAL_LENGTH_1B, 1 },
+ { ADDITIONAL_LENGTH_2B, 2 },
+ { ADDITIONAL_LENGTH_4B, 4 },
+ { ADDITIONAL_LENGTH_8B, 8 },
+ };
+
+ private const string SIMPLE_VALUE_FALSE = "F4";
+ private const string SIMPLE_VALUE_TRUE = "F5";
+ private const string SIMPLE_VALUE_NULL = "F6";
+ private const string SIMPLE_VALUE_UNDEF = "F7";
+
+ private static readonly Dictionary simpleValues = new Dictionary
+ {
+ { SIMPLE_VALUE_FALSE, false },
+ { SIMPLE_VALUE_TRUE, true },
+ { SIMPLE_VALUE_NULL, null },
+ { SIMPLE_VALUE_UNDEF, null }
+ };
+
+ ///
+ /// Decode incoming hexadecimal string of data and outputing decoded values
+ ///
+ /// Hexadecimal string to decode
+ /// Decoded value
+ /// Thrown when input is invalid or unsupported type
+ public static object Decode(string value)
+ {
+ value = SanitizeInput(value);
+ var data = SplitIntoBytes(value);
+ return ParseData(ref data);
+ }
+
+ private static object ParseData(ref List data)
+ {
+ if (data.Count == 0)
+ {
+ throw new Exception("Unexpected end of data");
+ }
+
+ var byteStr = data[0];
+ data.RemoveAt(0);
+
+ if (simpleValues.ContainsKey(byteStr))
+ {
+ return simpleValues[byteStr];
+ }
+
+ var byteValue = Convert.ToByte(byteStr, 16);
+ var type = (byte)(byteValue & TYPE_MASK);
+ var additional = (byte)(byteValue & ADDITIONAL_MASK);
+
+ switch (type)
+ {
+ case TYPE_NEGATIVE_INT:
+ case TYPE_UNSIGNED_INT:
+ long value;
+ if (additionalLength.Contains(additional))
+ {
+ value = Convert.ToInt64(GetData(ref data, additionalLengthBytes[additional]), 16);
+ }
+ else
+ {
+ value = additional;
+ }
+ if (type == TYPE_NEGATIVE_INT)
+ {
+ value = -1 - value;
+ }
+ return value;
+
+ case TYPE_FLOAT:
+ if (additional <= 23)
+ {
+ return additional;
+ }
+ else if (additional == ADDITIONAL_LENGTH_1B)
+ {
+ return GetData(ref data);
+ }
+ else
+ {
+ return DecodeFloat(GetData(ref data, additionalLengthBytes[additional]), additional);
+ }
+
+ case TYPE_BYTE_STRING:
+ // For byte strings, return the raw bytes
+ byte[] resultBytes;
+ if (additionalLength.Contains(additional))
+ {
+ var length = Convert.ToInt32(GetData(ref data, additionalLengthBytes[additional]), 16);
+ resultBytes = HexToBytes(GetData(ref data, length));
+ }
+ else if (additional == ADDITIONAL_TYPE_INDEFINITE)
+ {
+ resultBytes = HexToBytes(GetIndefiniteData(ref data));
+ }
+ else
+ {
+ resultBytes = HexToBytes(GetData(ref data, additional));
+ }
+ return resultBytes;
+
+ case TYPE_TEXT_STRING:
+ // For text strings, convert to UTF-8 string
+ string result;
+ if (additionalLength.Contains(additional))
+ {
+ var length = Convert.ToInt32(GetData(ref data, additionalLengthBytes[additional]), 16);
+ result = HexToBinary(GetData(ref data, length));
+ }
+ else if (additional == ADDITIONAL_TYPE_INDEFINITE)
+ {
+ result = HexToBinary(GetIndefiniteData(ref data));
+ }
+ else
+ {
+ result = HexToBinary(GetData(ref data, additional));
+ }
+ return result;
+
+ case TYPE_ARRAY:
+ var arrayResult = new List