Skip to content

Commit 9d943ee

Browse files
committed
feat: simple, low-allocation single-threaded observables
1 parent 418bc53 commit 9d943ee

27 files changed

+4153
-191
lines changed

.editorconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,5 @@ dotnet_diagnostic.IDE0010.severity = none
463463
dotnet_diagnostic.IDE0062.severity = warning
464464
# Don't make me use properties if I don't want to.
465465
dotnet_diagnostic.IDE0032.severity = none
466+
# Don't simplify new type names
467+
dotnet_diagnostic.IDE0090.severity = none

Chickensoft.Collections.Tests/src/BoxlessQueueTest.cs

Lines changed: 113 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,67 @@ namespace Chickensoft.Collections.Tests;
66
using Xunit;
77

88
public class BoxlessQueueTests {
9-
public readonly record struct ValueA;
10-
public readonly record struct ValueB;
9+
public readonly record struct ValueA(int Id);
10+
public readonly record struct ValueB(int Id);
11+
public readonly record struct ValueC(int Id);
1112

12-
public class TestValueHandler : IBoxlessValueHandler {
13-
public List<object> Values { get; } = [];
14-
public void HandleValue<TValue>(in TValue value) where TValue : struct =>
15-
Values.Add(value);
13+
public readonly struct TestValueHandler : IBoxlessValueHandler {
14+
public List<object> Values { get; }
15+
16+
public TestValueHandler() { Values = []; }
17+
18+
public readonly void HandleValue<TValue>(in TValue value)
19+
where TValue : struct => Values.Add(value);
1620
}
1721

1822
[Fact]
1923
public void Initializes() {
20-
var handler = new TestValueHandler();
21-
var queue = new BoxlessQueue(handler);
24+
var queue = new BoxlessQueue();
2225

23-
queue.Handler.ShouldBe(handler);
26+
queue.ShouldBeOfType<BoxlessQueue>();
2427
}
2528

2629
[Fact]
2730
public void EnqueueAndHandleValues() {
2831
var handler = new TestValueHandler();
29-
var queue = new BoxlessQueue(handler);
32+
var queue = new BoxlessQueue();
3033

3134
var valueA = new ValueA();
3235
var valueA2 = new ValueA();
3336
var valueB = new ValueB();
3437

38+
queue.Count.ShouldBe(0);
39+
3540
queue.Enqueue(valueA);
41+
42+
queue.Count.ShouldBe(1);
43+
3644
queue.Enqueue(valueA2);
3745
queue.Enqueue(valueB);
3846

47+
queue.Count.ShouldBe(3);
48+
3949
queue.HasValues.ShouldBeTrue();
4050

41-
queue.Dequeue();
42-
queue.Dequeue();
43-
queue.Dequeue();
51+
queue.Dequeue(in handler);
52+
53+
queue.Count.ShouldBe(2);
54+
55+
queue.Dequeue(in handler);
56+
57+
queue.Count.ShouldBe(1);
58+
59+
queue.Dequeue(in handler);
4460

4561
queue.HasValues.ShouldBeFalse();
46-
queue.Dequeue();
62+
queue.Dequeue(in handler);
4763
handler.Values.ShouldBe(new object[] { valueA, valueA2, valueB });
4864
}
4965

5066
[Fact]
5167
public void ClearQueue() {
5268
var handler = new TestValueHandler();
53-
var queue = new BoxlessQueue(handler);
69+
var queue = new BoxlessQueue();
5470

5571
queue.Enqueue(new ValueA());
5672
queue.Enqueue(new ValueB());
@@ -59,4 +75,86 @@ public void ClearQueue() {
5975

6076
queue.HasValues.ShouldBeFalse();
6177
}
78+
79+
[Fact]
80+
public void Peeks() {
81+
var handler = new TestValueHandler();
82+
var queue = new BoxlessQueue();
83+
84+
var valueA = new ValueA();
85+
var valueB = new ValueB();
86+
var valueC = new ValueC();
87+
88+
var valueD = new ValueA(1);
89+
var valueE = new ValueB(2);
90+
var valueF = new ValueC(3);
91+
92+
queue.Enqueue(valueA);
93+
queue.Enqueue(valueB);
94+
queue.Enqueue(valueC);
95+
queue.Enqueue(valueD);
96+
queue.Enqueue(valueE);
97+
queue.Enqueue(valueF);
98+
99+
queue.Peek(in handler).ShouldBeTrue();
100+
handler.Values.ShouldBe([valueA]);
101+
handler.Values.Clear();
102+
103+
queue.Discard();
104+
105+
queue.Peek(in handler).ShouldBeTrue();
106+
handler.Values.ShouldBe([valueB]);
107+
handler.Values.Clear();
108+
109+
queue.Discard();
110+
111+
queue.Peek(in handler).ShouldBeTrue();
112+
handler.Values.ShouldBe([valueC]);
113+
handler.Values.Clear();
114+
115+
queue.Discard();
116+
117+
queue.Peek(in handler).ShouldBeTrue();
118+
handler.Values.ShouldBe([valueD]);
119+
handler.Values.Clear();
120+
121+
queue.Discard();
122+
123+
queue.Peek(in handler).ShouldBeTrue();
124+
handler.Values.ShouldBe([valueE]);
125+
handler.Values.Clear();
126+
127+
queue.Discard();
128+
129+
queue.Peek(in handler).ShouldBeTrue();
130+
handler.Values.ShouldBe([valueF]);
131+
handler.Values.Clear();
132+
133+
queue.Discard();
134+
135+
queue.Peek(in handler).ShouldBeFalse();
136+
handler.Values.ShouldBeEmpty();
137+
138+
queue.Count.ShouldBe(0);
139+
140+
queue.Clear();
141+
142+
queue.Count.ShouldBe(0);
143+
}
144+
145+
[Fact]
146+
public void CannotDiscardOutOfRange() {
147+
var queue = new BoxlessQueue();
148+
149+
queue.Enqueue(new ValueA());
150+
queue.Enqueue(new ValueB());
151+
152+
queue.Discard(-1);
153+
154+
queue.Count.ShouldBe(2);
155+
156+
queue.Discard(3);
157+
158+
queue.Count.ShouldBe(0);
159+
}
62160
}

Chickensoft.Collections.Tests/src/MapTest.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ namespace Chickensoft.Collections.Tests;
66
using Shouldly;
77
using Xunit;
88

9+
#pragma warning disable CS0618 // obsolete
10+
911
public class MapTest {
1012
[Fact]
1113
public void Initializes()
@@ -290,3 +292,5 @@ public void KvpConstructor() {
290292
map.Values.ShouldBe([3, 2, 1]);
291293
}
292294
}
295+
296+
#pragma warning restore CS0618

Chickensoft.Collections.Tests/src/PoolTest.cs

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)