mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-15 14:19:29 +00:00
Client Web Socket implementation (#46)
This commit is contained in:
@@ -16,14 +16,14 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
private class AVLNode<TKey>
|
private class AVLNode<TKey>
|
||||||
{
|
{
|
||||||
public TKey Value;
|
public TKey Value;
|
||||||
public AVLNode<TKey> Left;
|
public AVLNode<TKey> Left = default!;
|
||||||
public AVLNode<TKey> Right;
|
public AVLNode<TKey> Right = default!;
|
||||||
public AVLNode(TKey value)
|
public AVLNode(TKey value)
|
||||||
{
|
{
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AVLNode<T> root;
|
AVLNode<T> root = default!;
|
||||||
private int count = 0;
|
private int count = 0;
|
||||||
private readonly bool isReadOnly = false;
|
private readonly bool isReadOnly = false;
|
||||||
#endregion
|
#endregion
|
||||||
@@ -98,7 +98,7 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
/// <param name="value">Value to be deleted.</param>
|
/// <param name="value">Value to be deleted.</param>
|
||||||
public bool Remove(T value)
|
public bool Remove(T value)
|
||||||
{
|
{
|
||||||
this.root = this.Delete(this.root, value);
|
this.root = this.Delete(this.root, value)!;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -115,19 +115,19 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
if (currentNode.Left != null)
|
if (currentNode.Left != null)
|
||||||
{
|
{
|
||||||
queue.Enqueue(currentNode.Left);
|
queue.Enqueue(currentNode.Left);
|
||||||
currentNode.Left = null;
|
currentNode.Left = default!;
|
||||||
this.count--;
|
this.count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentNode.Right != null)
|
if (currentNode.Right != null)
|
||||||
{
|
{
|
||||||
queue.Enqueue(currentNode.Right);
|
queue.Enqueue(currentNode.Right);
|
||||||
currentNode.Right = null;
|
currentNode.Right = default!;
|
||||||
this.count--;
|
this.count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.root = null;
|
this.root = default!;
|
||||||
this.count--;
|
this.count--;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -222,9 +222,8 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
|
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
private AVLNode<T> Delete(AVLNode<T> current, T target)
|
private AVLNode<T>? Delete(AVLNode<T> current, T target)
|
||||||
{
|
{
|
||||||
AVLNode<T> parent;
|
|
||||||
if (current == null)
|
if (current == null)
|
||||||
{ return null; }
|
{ return null; }
|
||||||
else
|
else
|
||||||
@@ -232,7 +231,7 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
//left subtree
|
//left subtree
|
||||||
if (target.CompareTo(current.Value) < 0)
|
if (target.CompareTo(current.Value) < 0)
|
||||||
{
|
{
|
||||||
current.Left = this.Delete(current.Left, target);
|
current.Left = this.Delete(current.Left, target)!;
|
||||||
if (this.BalanceFactor(current) == -2)//here
|
if (this.BalanceFactor(current) == -2)//here
|
||||||
{
|
{
|
||||||
if (this.BalanceFactor(current.Right) <= 0)
|
if (this.BalanceFactor(current.Right) <= 0)
|
||||||
@@ -248,7 +247,7 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
//right subtree
|
//right subtree
|
||||||
else if (target.CompareTo(current.Value) > 0)
|
else if (target.CompareTo(current.Value) > 0)
|
||||||
{
|
{
|
||||||
current.Right = this.Delete(current.Right, target);
|
current.Right = this.Delete(current.Right, target)!;
|
||||||
if (this.BalanceFactor(current) == 2)
|
if (this.BalanceFactor(current) == 2)
|
||||||
{
|
{
|
||||||
if (this.BalanceFactor(current.Left) >= 0)
|
if (this.BalanceFactor(current.Left) >= 0)
|
||||||
@@ -268,14 +267,14 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
if (current.Right != null)
|
if (current.Right != null)
|
||||||
{
|
{
|
||||||
//delete its inorder successor
|
//delete its inorder successor
|
||||||
parent = current.Right;
|
var parent = current.Right;
|
||||||
while (parent.Left != null)
|
while (parent.Left != null)
|
||||||
{
|
{
|
||||||
parent = parent.Left;
|
parent = parent.Left;
|
||||||
}
|
}
|
||||||
|
|
||||||
current.Value = parent.Value;
|
current.Value = parent.Value;
|
||||||
current.Right = this.Delete(current.Right, parent.Value);
|
current.Right = this.Delete(current.Right, parent.Value)!;
|
||||||
if (this.BalanceFactor(current) == 2)//rebalancing
|
if (this.BalanceFactor(current) == 2)//rebalancing
|
||||||
{
|
{
|
||||||
if (this.BalanceFactor(current.Left) >= 0)
|
if (this.BalanceFactor(current.Left) >= 0)
|
||||||
@@ -294,7 +293,7 @@ public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
|
|||||||
|
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
private AVLNode<T> Find(T target, AVLNode<T> current)
|
private AVLNode<T>? Find(T target, AVLNode<T> current)
|
||||||
{
|
{
|
||||||
if (current == null)
|
if (current == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
private FibonacciNode<T> root;
|
private FibonacciNode<T> root = default!;
|
||||||
private int count;
|
private int count;
|
||||||
#endregion
|
#endregion
|
||||||
#region Properties
|
#region Properties
|
||||||
@@ -53,8 +53,8 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
Value = value,
|
Value = value,
|
||||||
Marked = false,
|
Marked = false,
|
||||||
Child = null,
|
Child = default!,
|
||||||
Parent = null,
|
Parent = default!,
|
||||||
Degree = 0
|
Degree = 0
|
||||||
};
|
};
|
||||||
node.Previous = node.Next = node;
|
node.Previous = node.Next = node;
|
||||||
@@ -68,7 +68,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
public void Merge(FibonacciHeap<T> otherHeap)
|
public void Merge(FibonacciHeap<T> otherHeap)
|
||||||
{
|
{
|
||||||
this.root = this.Merge(this.root, otherHeap.root);
|
this.root = this.Merge(this.root, otherHeap.root);
|
||||||
otherHeap.root = null;
|
otherHeap.root = default!;
|
||||||
this.count += otherHeap.count;
|
this.count += otherHeap.count;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -80,7 +80,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
var currentRoot = this.root;
|
var currentRoot = this.root;
|
||||||
if (currentRoot != null)
|
if (currentRoot != null)
|
||||||
{
|
{
|
||||||
this.root = this.RemoveMinimum(this.root);
|
this.root = this.RemoveMinimum(this.root)!;
|
||||||
this.count--;
|
this.count--;
|
||||||
return currentRoot.Value;
|
return currentRoot.Value;
|
||||||
}
|
}
|
||||||
@@ -115,8 +115,8 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
this.Remove(this.root);
|
this.Remove(this.root);
|
||||||
this.root.Next = this.root.Previous = this.root.Parent = this.root.Child = null;
|
this.root.Next = this.root.Previous = this.root.Parent = this.root.Child = default!;
|
||||||
this.root = null;
|
this.root = default!;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the heap structure as an array. Array is not sorted other than the
|
/// Return the heap structure as an array. Array is not sorted other than the
|
||||||
@@ -127,7 +127,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
if (this.count == 0)
|
if (this.count == 0)
|
||||||
{
|
{
|
||||||
return null;
|
return default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
var array = new T[this.count];
|
var array = new T[this.count];
|
||||||
@@ -212,12 +212,12 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
this.Remove(current.Child);
|
this.Remove(current.Child);
|
||||||
if (current.Parent != null)
|
if (current.Parent != null)
|
||||||
{
|
{
|
||||||
current.Parent.Child = null;
|
current.Parent.Child = default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = current.Next;
|
current = current.Next;
|
||||||
} while (current != node);
|
} while (current != node);
|
||||||
current.Next = current.Previous = current.Child = current.Parent = null;
|
current.Next = current.Previous = current.Child = current.Parent = default!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -279,7 +279,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
current.Marked = false;
|
current.Marked = false;
|
||||||
current.Parent = null;
|
current.Parent = default!;
|
||||||
current = current.Next;
|
current = current.Next;
|
||||||
} while (current != node);
|
} while (current != node);
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">Root of the provided tree.</param>
|
/// <param name="node">Root of the provided tree.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private FibonacciNode<T> RemoveMinimum(FibonacciNode<T> node)
|
private FibonacciNode<T>? RemoveMinimum(FibonacciNode<T> node)
|
||||||
{
|
{
|
||||||
this.RemoveParent(node.Child);
|
this.RemoveParent(node.Child);
|
||||||
if (node.Next == node)
|
if (node.Next == node)
|
||||||
@@ -318,7 +318,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
trees[node.Degree] = null;
|
trees[node.Degree] = default!;
|
||||||
if (node.Value.CompareTo(t.Value) < 0)
|
if (node.Value.CompareTo(t.Value) < 0)
|
||||||
{
|
{
|
||||||
t.Previous.Next = t.Next;
|
t.Previous.Next = t.Next;
|
||||||
@@ -379,7 +379,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
if (node.Next == node)
|
if (node.Next == node)
|
||||||
{
|
{
|
||||||
node.Parent.Child = null;
|
node.Parent.Child = default!;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -413,13 +413,13 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
root = this.Cut(root, node);
|
root = this.Cut(root, node);
|
||||||
var parent = node.Parent;
|
var parent = node.Parent;
|
||||||
node.Parent = null;
|
node.Parent = default!;
|
||||||
while (parent != null && parent.Marked)
|
while (parent != null && parent.Marked)
|
||||||
{
|
{
|
||||||
root = this.Cut(root, parent);
|
root = this.Cut(root, parent);
|
||||||
node = parent;
|
node = parent;
|
||||||
parent = node.Parent;
|
parent = node.Parent;
|
||||||
node.Parent = null;
|
node.Parent = default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent != null && parent.Parent != null)
|
if (parent != null && parent.Parent != null)
|
||||||
@@ -449,7 +449,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
var node = root;
|
var node = root;
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
return null;
|
return default!;
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -467,7 +467,7 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
|
|
||||||
node = node.Next;
|
node = node.Next;
|
||||||
} while (node != root);
|
} while (node != root);
|
||||||
return null;
|
return default!;
|
||||||
}
|
}
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
{
|
{
|
||||||
@@ -479,11 +479,11 @@ public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
|
|||||||
internal sealed class FibonacciNode<T>
|
internal sealed class FibonacciNode<T>
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
private FibonacciNode<T> previous;
|
private FibonacciNode<T> previous = default!;
|
||||||
private FibonacciNode<T> next;
|
private FibonacciNode<T> next = default!;
|
||||||
private FibonacciNode<T> child;
|
private FibonacciNode<T> child = default!;
|
||||||
private FibonacciNode<T> parent;
|
private FibonacciNode<T> parent = default!;
|
||||||
private T value;
|
private T value = default!;
|
||||||
private int degree;
|
private int degree;
|
||||||
private bool marked;
|
private bool marked;
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public sealed class SkipList<T> : ICollection<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
this.maxLevel = maxLevel;
|
this.maxLevel = maxLevel;
|
||||||
this.random = new Random();
|
this.random = new Random();
|
||||||
this.head = new NodeSet<T>(default, maxLevel);
|
this.head = new NodeSet<T>(default!, maxLevel);
|
||||||
this.end = this.head;
|
this.end = this.head;
|
||||||
for (var i = 0; i <= maxLevel; i++)
|
for (var i = 0; i <= maxLevel; i++)
|
||||||
{
|
{
|
||||||
@@ -242,7 +242,7 @@ public sealed class SkipList<T> : ICollection<T> where T : IComparable<T>
|
|||||||
return curNode;
|
return curNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return default!;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
public TKey Key;
|
public TKey Key;
|
||||||
public int Priority;
|
public int Priority;
|
||||||
public Node<TKey> Left, Right;
|
public Node<TKey>? Left, Right;
|
||||||
public Node(TKey key, int priority)
|
public Node(TKey key, int priority)
|
||||||
{
|
{
|
||||||
this.Key = key;
|
this.Key = key;
|
||||||
@@ -23,7 +23,7 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private readonly Random randomGen;
|
private readonly Random randomGen;
|
||||||
private Node<T> root;
|
private Node<T> root = default!;
|
||||||
private int count;
|
private int count;
|
||||||
#endregion
|
#endregion
|
||||||
#region Properties
|
#region Properties
|
||||||
@@ -77,7 +77,7 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
this.Clear(this.root);
|
this.Clear(this.root);
|
||||||
this.root = null;
|
this.root = default!;
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -93,7 +93,7 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
/// Returns the treap structure as an ordered array.
|
/// Returns the treap structure as an ordered array.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Ordered array containing the values stored in the treap.</returns>
|
/// <returns>Ordered array containing the values stored in the treap.</returns>
|
||||||
public T[] ToArray()
|
public T[]? ToArray()
|
||||||
{
|
{
|
||||||
if (this.root != null)
|
if (this.root != null)
|
||||||
{
|
{
|
||||||
@@ -104,7 +104,7 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return null;
|
return default!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -135,16 +135,16 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
}
|
}
|
||||||
else if (key.CompareTo(node.Key) <= 0)
|
else if (key.CompareTo(node.Key) <= 0)
|
||||||
{
|
{
|
||||||
node.Left = this.InsertNode(node.Left, key);
|
node.Left = this.InsertNode(node.Left!, key);
|
||||||
if (node.Left.Priority > node.Priority)
|
if (node.Left!.Priority > node.Priority)
|
||||||
{
|
{
|
||||||
node = this.RotateRight(node);
|
node = this.RotateRight(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node.Right = this.InsertNode(node.Right, key);
|
node.Right = this.InsertNode(node.Right!, key);
|
||||||
if (node.Right.Priority > node.Priority)
|
if (node.Right!.Priority > node.Priority)
|
||||||
{
|
{
|
||||||
node = this.RotateLeft(node);
|
node = this.RotateLeft(node);
|
||||||
}
|
}
|
||||||
@@ -156,20 +156,20 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
return node;
|
return node!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.CompareTo(node.Key) < 0)
|
if (key.CompareTo(node.Key) < 0)
|
||||||
{
|
{
|
||||||
node.Left = this.RemoveNode(node.Left, key);
|
node.Left = this.RemoveNode(node.Left!, key);
|
||||||
}
|
}
|
||||||
else if (key.CompareTo(node.Key) > 0)
|
else if (key.CompareTo(node.Key) > 0)
|
||||||
{
|
{
|
||||||
node.Right = this.RemoveNode(node.Right, key);
|
node.Right = this.RemoveNode(node.Right!, key);
|
||||||
}
|
}
|
||||||
else if (node.Left == null)
|
else if (node.Left == null)
|
||||||
{
|
{
|
||||||
node = node.Right;
|
node = node.Right!;
|
||||||
}
|
}
|
||||||
else if (node.Right == null)
|
else if (node.Right == null)
|
||||||
{
|
{
|
||||||
@@ -178,26 +178,26 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
else if (node.Left.Priority < node.Right.Priority)
|
else if (node.Left.Priority < node.Right.Priority)
|
||||||
{
|
{
|
||||||
node = this.RotateLeft(node);
|
node = this.RotateLeft(node);
|
||||||
node.Left = this.RemoveNode(node.Left, key);
|
node.Left = this.RemoveNode(node.Left!, key);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node = this.RotateRight(node);
|
node = this.RotateRight(node);
|
||||||
node.Right = this.RemoveNode(node.Right, key);
|
node.Right = this.RemoveNode(node.Right!, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
private Node<T> RotateRight(Node<T> node)
|
private Node<T> RotateRight(Node<T> node)
|
||||||
{
|
{
|
||||||
Node<T> temp = node.Left, temp2 = temp.Right;
|
Node<T> temp = node.Left!, temp2 = temp.Right!;
|
||||||
temp.Right = node;
|
temp.Right = node;
|
||||||
node.Left = temp2;
|
node.Left = temp2;
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
private Node<T> RotateLeft(Node<T> node)
|
private Node<T> RotateLeft(Node<T> node)
|
||||||
{
|
{
|
||||||
Node<T> temp = node.Right, temp2 = temp.Left;
|
Node<T> temp = node.Right!, temp2 = temp.Left!;
|
||||||
temp.Left = node;
|
temp.Left = node;
|
||||||
node.Right = temp2;
|
node.Right = temp2;
|
||||||
return temp;
|
return temp;
|
||||||
@@ -220,26 +220,26 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
return node;
|
return node!;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (node.Key.CompareTo(key) < 0)
|
if (node.Key.CompareTo(key) < 0)
|
||||||
{
|
{
|
||||||
var found = this.Find(node.Left, key);
|
var found = this.Find(node.Left!, key);
|
||||||
if (found == null)
|
if (found == null)
|
||||||
{
|
{
|
||||||
found = this.Find(node.Right, key);
|
found = this.Find(node.Right!, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
else if (node.Key.CompareTo(key) > 0)
|
else if (node.Key.CompareTo(key) > 0)
|
||||||
{
|
{
|
||||||
var found = this.Find(node.Right, key);
|
var found = this.Find(node.Right!, key);
|
||||||
if (found == null)
|
if (found == null)
|
||||||
{
|
{
|
||||||
found = this.Find(node.Left, key);
|
found = this.Find(node.Left!, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
@@ -254,10 +254,10 @@ public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
|
|||||||
{
|
{
|
||||||
if (node != null)
|
if (node != null)
|
||||||
{
|
{
|
||||||
this.ToArray(node.Left, ref array, ref index);
|
this.ToArray(node.Left!, ref array, ref index);
|
||||||
array[index] = node.Key;
|
array[index] = node.Key;
|
||||||
index++;
|
index++;
|
||||||
this.ToArray(node.Right, ref array, ref index);
|
this.ToArray(node.Right!, ref array, ref index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private IEnumerator<T> GetEnumerator(Node<T> currentNode)
|
private IEnumerator<T> GetEnumerator(Node<T> currentNode)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace System.Extensions;
|
|||||||
|
|
||||||
public static class ObjectExtensions
|
public static class ObjectExtensions
|
||||||
{
|
{
|
||||||
public static T Deserialize<T>(this string serialized)
|
public static T? Deserialize<T>(this string serialized)
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
if (serialized.IsNullOrWhiteSpace())
|
if (serialized.IsNullOrWhiteSpace())
|
||||||
@@ -31,7 +31,7 @@ public static class ObjectExtensions
|
|||||||
return (T)obj;
|
return (T)obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T As<T>(this object obj) where T : class
|
public static T? As<T>(this object obj) where T : class
|
||||||
{
|
{
|
||||||
return obj as T;
|
return obj as T;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public static class Optional
|
|||||||
return new Optional<T>.None();
|
return new Optional<T>.None();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<T> FromValue<T>(T value)
|
public static Optional<T> FromValue<T>(T? value)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
|
|
||||||
private T Value { get; }
|
private T Value { get; }
|
||||||
|
|
||||||
public T ExtractValue()
|
public T? ExtractValue()
|
||||||
{
|
{
|
||||||
if (this is None)
|
if (this is None)
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
return this.Value;
|
return this.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Optional<T> Do(Action<T> onSome, Action onNone)
|
public Optional<T> Do(Action<T>? onSome, Action? onNone)
|
||||||
{
|
{
|
||||||
if (onSome is null)
|
if (onSome is null)
|
||||||
{
|
{
|
||||||
@@ -61,7 +61,7 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Optional<T> DoAny(Action<T> onSome = null, Action onNone = null)
|
public Optional<T> DoAny(Action<T>? onSome = default, Action? onNone = default)
|
||||||
{
|
{
|
||||||
if (this is Some)
|
if (this is Some)
|
||||||
{
|
{
|
||||||
@@ -74,7 +74,7 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Optional<V> Switch<V>(Func<T, V> onSome, Func<V> onNone)
|
public Optional<V> Switch<V>(Func<T, V>? onSome, Func<V>? onNone)
|
||||||
{
|
{
|
||||||
if (onSome is null)
|
if (onSome is null)
|
||||||
{
|
{
|
||||||
@@ -95,7 +95,7 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
return Optional.FromValue(onNone.Invoke());
|
return Optional.FromValue(onNone.Invoke());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Optional<V> SwitchAny<V>(Func<T, V> onSome = null, Func<V> onNone = null)
|
public Optional<V> SwitchAny<V>(Func<T, V>? onSome = null, Func<V>? onNone = null)
|
||||||
{
|
{
|
||||||
if (this is Some)
|
if (this is Some)
|
||||||
{
|
{
|
||||||
@@ -107,7 +107,7 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (obj is Optional<T>)
|
if (obj is Optional<T>)
|
||||||
{
|
{
|
||||||
@@ -117,17 +117,17 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
return base.Equals(obj);
|
return base.Equals(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(Optional<T> other)
|
public bool Equals(Optional<T>? other)
|
||||||
{
|
{
|
||||||
if (this is Some && other is Some)
|
if (this is Some && other is Some)
|
||||||
{
|
{
|
||||||
return this.As<Some>().Equals(other.As<Some>());
|
return this.As<Some>() is Some some ? some.Equals(other.As<Some>()) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator Optional<T>(T value)
|
public static implicit operator Optional<T>(T? value)
|
||||||
{
|
{
|
||||||
return Optional.FromValue(value);
|
return Optional.FromValue(value);
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (obj is Some)
|
if (obj is Some)
|
||||||
{
|
{
|
||||||
@@ -153,40 +153,40 @@ public abstract class Optional<T> : IEquatable<Optional<T>>
|
|||||||
return base.Equals(obj);
|
return base.Equals(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(Some other)
|
public bool Equals(Some? other)
|
||||||
{
|
{
|
||||||
if (other is None)
|
if (other is None)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other is Some)
|
if (other is not null)
|
||||||
{
|
{
|
||||||
return this.Value.Equals(other.Value);
|
return this.Value is not null && this.Value.Equals(other.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator ==(Some left, Some right)
|
public static bool operator ==(Some? left, Some right)
|
||||||
{
|
{
|
||||||
return left?.Equals(right) == true;
|
return left?.Equals(right) == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(Some left, Some right)
|
public static bool operator !=(Some? left, Some right)
|
||||||
{
|
{
|
||||||
return left?.Equals(right) != true;
|
return left?.Equals(right) != true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return this.Value is object ? this.Value.GetHashCode() : this.As<object>().GetHashCode();
|
return this.Value is object ? this.Value.GetHashCode() : this.As<object>() is object obj ? obj.GetHashCode() : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class None : Optional<T>
|
internal class None : Optional<T>
|
||||||
{
|
{
|
||||||
public None() : base(default)
|
public None() : base(default!)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
public class Result<TSuccess, TFailure>
|
public class Result<TSuccess, TFailure>
|
||||||
{
|
{
|
||||||
private readonly object value;
|
private readonly object? value;
|
||||||
|
|
||||||
public Result(TSuccess successValue)
|
public Result(TSuccess successValue)
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@ public class Result<TSuccess, TFailure>
|
|||||||
this.value = failureValue;
|
this.value = failureValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryExtractSuccess(out TSuccess successValue)
|
public bool TryExtractSuccess(out TSuccess? successValue)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (this.value is TSuccess success)
|
if (this.value is TSuccess success)
|
||||||
@@ -27,7 +27,7 @@ public class Result<TSuccess, TFailure>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool TryExtractFailure(out TFailure failureValue)
|
public bool TryExtractFailure(out TFailure? failureValue)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (this.value is TFailure failure)
|
if (this.value is TFailure failure)
|
||||||
@@ -64,7 +64,7 @@ public class Result<TSuccess, TFailure>
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Result<TSuccess, TFailure> DoAny(Action onSuccess = null, Action onFailure = null)
|
public Result<TSuccess, TFailure> DoAny(Action? onSuccess = null, Action? onFailure = null)
|
||||||
{
|
{
|
||||||
if (this.value is TSuccess)
|
if (this.value is TSuccess)
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,7 @@ public class Result<TSuccess, TFailure>
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Result<TSuccess, TFailure> DoAny(Action<TSuccess> onSuccess = null, Action<TFailure> onFailure = null)
|
public Result<TSuccess, TFailure> DoAny(Action<TSuccess>? onSuccess = null, Action<TFailure>? onFailure = null)
|
||||||
{
|
{
|
||||||
if (this.value is TSuccess success)
|
if (this.value is TSuccess success)
|
||||||
{
|
{
|
||||||
@@ -136,7 +136,7 @@ public class Result<TSuccess, TFailure>
|
|||||||
|
|
||||||
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
||||||
}
|
}
|
||||||
public T SwitchAny<T>(Func<TSuccess, T> onSuccess = null, Func<TFailure, T> onFailure = null)
|
public T? SwitchAny<T>(Func<TSuccess, T>? onSuccess = null, Func<TFailure, T>? onFailure = null)
|
||||||
{
|
{
|
||||||
if (this.value is TSuccess success)
|
if (this.value is TSuccess success)
|
||||||
{
|
{
|
||||||
@@ -176,11 +176,11 @@ public class Result<TSuccess, TFailure>
|
|||||||
{
|
{
|
||||||
if (this.value is TSuccess success)
|
if (this.value is TSuccess success)
|
||||||
{
|
{
|
||||||
return Result<V, K>.Success(onSuccess is null ? default : onSuccess.Invoke(success));
|
return Result<V, K>.Success(onSuccess is not null ? onSuccess.Invoke(success) : default!);
|
||||||
}
|
}
|
||||||
else if (this.value is TFailure failure)
|
else if (this.value is TFailure failure)
|
||||||
{
|
{
|
||||||
return Result<V, K>.Failure(onFailure is null ? default : onFailure.Invoke(failure));
|
return Result<V, K>.Failure(onFailure is not null ? onFailure.Invoke(failure) : default!);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
|
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public static class TaskExtensions
|
|||||||
{
|
{
|
||||||
synch.EndMessageLoop();
|
synch.EndMessageLoop();
|
||||||
}
|
}
|
||||||
}, null);
|
}, default!);
|
||||||
synch.BeginMessageLoop();
|
synch.BeginMessageLoop();
|
||||||
|
|
||||||
SynchronizationContext.SetSynchronizationContext(oldContext);
|
SynchronizationContext.SetSynchronizationContext(oldContext);
|
||||||
@@ -115,16 +115,16 @@ public static class TaskExtensions
|
|||||||
{
|
{
|
||||||
synch.EndMessageLoop();
|
synch.EndMessageLoop();
|
||||||
}
|
}
|
||||||
}, null);
|
}, default!);
|
||||||
synch.BeginMessageLoop();
|
synch.BeginMessageLoop();
|
||||||
SynchronizationContext.SetSynchronizationContext(oldContext);
|
SynchronizationContext.SetSynchronizationContext(oldContext);
|
||||||
return ret;
|
return ret!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExclusiveSynchronizationContext : SynchronizationContext
|
private class ExclusiveSynchronizationContext : SynchronizationContext
|
||||||
{
|
{
|
||||||
private bool done;
|
private bool done;
|
||||||
public Exception InnerException { get; set; }
|
public Exception? InnerException { get; set; }
|
||||||
readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
|
readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
|
||||||
readonly Queue<Tuple<SendOrPostCallback, object>> items =
|
readonly Queue<Tuple<SendOrPostCallback, object>> items =
|
||||||
new Queue<Tuple<SendOrPostCallback, object>>();
|
new Queue<Tuple<SendOrPostCallback, object>>();
|
||||||
@@ -146,14 +146,14 @@ public static class TaskExtensions
|
|||||||
|
|
||||||
public void EndMessageLoop()
|
public void EndMessageLoop()
|
||||||
{
|
{
|
||||||
this.Post(_ => this.done = true, null);
|
this.Post(_ => this.done = true, default!);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginMessageLoop()
|
public void BeginMessageLoop()
|
||||||
{
|
{
|
||||||
while (!this.done)
|
while (!this.done)
|
||||||
{
|
{
|
||||||
Tuple<SendOrPostCallback, object> task = null;
|
Tuple<SendOrPostCallback, object> task = default!;
|
||||||
lock (this.items)
|
lock (this.items)
|
||||||
{
|
{
|
||||||
if (this.items.Count > 0)
|
if (this.items.Count > 0)
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ public sealed class HttpClient<Tscope> : IHttpClient<Tscope>, IDisposable
|
|||||||
}
|
}
|
||||||
remove
|
remove
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||||
this.eventEmitted -= value;
|
this.eventEmitted -= value;
|
||||||
|
#pragma warning restore CS8601 // Possible null reference assignment.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Uri BaseAddress { get => this.httpClient.BaseAddress; set => this.httpClient.BaseAddress = value; }
|
public Uri BaseAddress { get => this.httpClient.BaseAddress; set => this.httpClient.BaseAddress = value; }
|
||||||
@@ -27,20 +29,26 @@ public sealed class HttpClient<Tscope> : IHttpClient<Tscope>, IDisposable
|
|||||||
public long MaxResponseContentBufferSize { get => this.httpClient.MaxResponseContentBufferSize; set => this.httpClient.MaxResponseContentBufferSize = value; }
|
public long MaxResponseContentBufferSize { get => this.httpClient.MaxResponseContentBufferSize; set => this.httpClient.MaxResponseContentBufferSize = value; }
|
||||||
public TimeSpan Timeout { get => this.httpClient.Timeout; set => this.httpClient.Timeout = value; }
|
public TimeSpan Timeout { get => this.httpClient.Timeout; set => this.httpClient.Timeout = value; }
|
||||||
|
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
public HttpClient()
|
public HttpClient()
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
{
|
{
|
||||||
this.httpClient = new HttpClient();
|
this.httpClient = new HttpClient();
|
||||||
this.scope = typeof(Tscope);
|
this.scope = typeof(Tscope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
public HttpClient(
|
public HttpClient(
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
HttpMessageHandler handler)
|
HttpMessageHandler handler)
|
||||||
{
|
{
|
||||||
this.httpClient = new HttpClient(handler);
|
this.httpClient = new HttpClient(handler);
|
||||||
this.scope = typeof(Tscope);
|
this.scope = typeof(Tscope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
public HttpClient(
|
public HttpClient(
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
HttpMessageHandler handler,
|
HttpMessageHandler handler,
|
||||||
bool disposeHandler)
|
bool disposeHandler)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,10 +7,11 @@
|
|||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
<RootNamespace>System</RootNamespace>
|
<RootNamespace>System</RootNamespace>
|
||||||
<Version>1.5</Version>
|
<Version>1.6</Version>
|
||||||
<Authors>Alexandru Macocian</Authors>
|
<Authors>Alexandru Macocian</Authors>
|
||||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||||
<Description>Extensions for the System namespace</Description>
|
<Description>Extensions for the System namespace</Description>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ public class PriorityThreadPool : IDisposable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private volatile List<WorkerThread> threadpool;
|
private volatile List<WorkerThread> threadpool;
|
||||||
private volatile PriorityQueue<QueueEntry> tasks;
|
private volatile PriorityQueue<QueueEntry> tasks;
|
||||||
private Thread observer;
|
private Thread? observer;
|
||||||
private CancellationTokenSource observerCancellationTokenSource = new CancellationTokenSource();
|
private CancellationTokenSource observerCancellationTokenSource = new CancellationTokenSource();
|
||||||
private readonly object tasksLock = new object();
|
private readonly object tasksLock = new object();
|
||||||
private struct WorkerThread
|
private struct WorkerThread
|
||||||
@@ -307,7 +307,7 @@ public class PriorityThreadPool : IDisposable
|
|||||||
//Finally, release the lock and invoke the task.
|
//Finally, release the lock and invoke the task.
|
||||||
|
|
||||||
thisWorkerThread.Working = true;
|
thisWorkerThread.Working = true;
|
||||||
QueueEntry task = null;
|
QueueEntry task = default!;
|
||||||
while (!Monitor.TryEnter(this.tasksLock))
|
while (!Monitor.TryEnter(this.tasksLock))
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
@@ -451,7 +451,7 @@ public class PriorityThreadPool : IDisposable
|
|||||||
/// Find a thread with Lowest or BelowNormal priority.
|
/// Find a thread with Lowest or BelowNormal priority.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Thread with low priority.</returns>
|
/// <returns>Thread with low priority.</returns>
|
||||||
private Thread FindThreadWithLowPriority()
|
private Thread? FindThreadWithLowPriority()
|
||||||
{
|
{
|
||||||
foreach (var t in this.threadpool)
|
foreach (var t in this.threadpool)
|
||||||
{
|
{
|
||||||
@@ -461,13 +461,13 @@ public class PriorityThreadPool : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return default;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Find a thread with BelowNormal or Normal priority.
|
/// Find a thread with BelowNormal or Normal priority.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Thread with BelowNormal or Normal priority.</returns>
|
/// <returns>Thread with BelowNormal or Normal priority.</returns>
|
||||||
private Thread FindThreadWithAcceptablePriority()
|
private Thread? FindThreadWithAcceptablePriority()
|
||||||
{
|
{
|
||||||
foreach (var t in this.threadpool)
|
foreach (var t in this.threadpool)
|
||||||
{
|
{
|
||||||
@@ -477,7 +477,7 @@ public class PriorityThreadPool : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return default;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Downgrades the priority of a thread one level.
|
/// Downgrades the priority of a thread one level.
|
||||||
@@ -560,9 +560,9 @@ public class PriorityThreadPool : IDisposable
|
|||||||
this.tasks.Clear();
|
this.tasks.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.threadpool = null;
|
this.threadpool = default!;
|
||||||
this.tasks = null;
|
this.tasks = default!;
|
||||||
this.observer = null;
|
this.observer = default;
|
||||||
this.disposedValue = true;
|
this.disposedValue = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Extensions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace System.Net.WebSockets;
|
||||||
|
|
||||||
|
// TODO: Cannot properly test because ClientWebSocket is sealed
|
||||||
|
public sealed class ClientWebSocket<TScope> : IClientWebSocket<TScope>, IDisposable
|
||||||
|
{
|
||||||
|
private readonly ILogger<TScope>? logger;
|
||||||
|
private readonly ClientWebSocket internalWebSocket = new();
|
||||||
|
|
||||||
|
public ClientWebSocketOptions Options => this.internalWebSocket.Options;
|
||||||
|
|
||||||
|
public WebSocketCloseStatus? CloseStatus => this.internalWebSocket.CloseStatus;
|
||||||
|
|
||||||
|
public string CloseStatusDescription => this.internalWebSocket.CloseStatusDescription;
|
||||||
|
|
||||||
|
public string SubProtocol => this.internalWebSocket.SubProtocol;
|
||||||
|
|
||||||
|
public WebSocketState State => this.internalWebSocket.State;
|
||||||
|
|
||||||
|
public ClientWebSocket()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientWebSocket(ILogger<TScope> logger)
|
||||||
|
{
|
||||||
|
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientWebSocket(ClientWebSocket clientWebSocket, ILogger<TScope> logger)
|
||||||
|
{
|
||||||
|
this.internalWebSocket = clientWebSocket.ThrowIfNull(nameof(clientWebSocket));
|
||||||
|
this.logger = logger.ThrowIfNull(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.internalWebSocket?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Abort()
|
||||||
|
{
|
||||||
|
this.internalWebSocket.Abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var scopedLogger = this.logger?.CreateScopedLogger(nameof(CloseAsync), string.Empty);
|
||||||
|
scopedLogger?.LogInformation($"Closing websocket. Status [{closeStatus}]. Status Description [{statusDescription}]");
|
||||||
|
return this.internalWebSocket.CloseAsync(closeStatus, statusDescription, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var scopedLogger = this.logger?.CreateScopedLogger(nameof(CloseOutputAsync), string.Empty);
|
||||||
|
scopedLogger?.LogInformation($"Closing output. Status [{closeStatus}]. Status Description [{statusDescription}]");
|
||||||
|
return this.internalWebSocket.CloseOutputAsync(closeStatus, statusDescription, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ConnectAsync(Uri uri, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var scopedLogger = this.logger?.CreateScopedLogger(nameof(ConnectAsync), string.Empty);
|
||||||
|
scopedLogger?.LogInformation($"Connecting to {uri}");
|
||||||
|
return this.ConnectAsync(uri, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var scopedLogger = this.logger?.CreateScopedLogger(nameof(ConnectAsync), string.Empty);
|
||||||
|
scopedLogger?.LogInformation($"Attempting to receive bytes");
|
||||||
|
var result = await this.ReceiveAsync(buffer, cancellationToken);
|
||||||
|
scopedLogger?.LogInformation($"Received message [{result.MessageType}]");
|
||||||
|
scopedLogger?.LogDebug($"Type: {result.MessageType}\nCount: {result.Count}\nEndOfMessage: {result.EndOfMessage}\nCloseStatus: {result.CloseStatus}\nCloseStatusDescription: {result.CloseStatusDescription}");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var scopedLogger = this.logger?.CreateScopedLogger(nameof(SendAsync), string.Empty);
|
||||||
|
scopedLogger?.LogInformation($"Sending bytes");
|
||||||
|
scopedLogger?.LogDebug($"Type: {messageType}\nCount: {buffer.Count}\nEndOfMessage: {endOfMessage}");
|
||||||
|
return this.SendAsync(buffer, messageType, endOfMessage, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace System.Net.WebSockets;
|
||||||
|
|
||||||
|
public interface IClientWebSocket<TScope>
|
||||||
|
{
|
||||||
|
WebSocketCloseStatus? CloseStatus { get; }
|
||||||
|
|
||||||
|
string CloseStatusDescription { get; }
|
||||||
|
|
||||||
|
ClientWebSocketOptions Options { get; }
|
||||||
|
|
||||||
|
WebSocketState State { get; }
|
||||||
|
|
||||||
|
string SubProtocol { get; }
|
||||||
|
|
||||||
|
void Abort();
|
||||||
|
|
||||||
|
Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task ConnectAsync(Uri uri, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
void Dispose();
|
||||||
|
|
||||||
|
Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user